Ответ 1
Полиморфная рекурсия (когда функция вызывает себя с типом, отличным от того, у которого она была вызвана) всегда требует сигнатуры типа. Полное объяснение приведено в разделе 4.4.1 отчета Haskell 2010:
Если переменная
f
определена без предоставления соответствующего объявления сигнатуры типа, то каждое использованиеf
вне своей собственной группы объявлений (см. Раздел 4.5) рассматривается как наличие соответствующего предполагаемого или основного типа. Однако, чтобы гарантировать, что вывод типа все еще возможен, определяющее вхождение и все виды использованияf
в его группе объявлений должны иметь один и тот же мономорфный тип (из которого основной тип получается путем обобщения, как описано в Разделе 4.5.2).
Позже в этом же разделе представлен пример полиморфной рекурсии, поддерживаемой сигнатурой типа.
Насколько я понимаю, вывод без помощи типа обычно неразрешим при наличии полиморфной рекурсии, поэтому Хаскелл даже не пытается.
В этом случае проверка типов начинается с
w :: a
где a
является мета-переменной. Поскольку fromInteger
вызывается с w
в качестве аргумента в своем собственном объявлении (и, следовательно, в своей группе объявлений), средство проверки типов объединяет a
с Integer
. Не осталось переменных для обобщения.
Небольшая модификация вашей программы дает другой результат по той же причине:
v = fromIntegral v
Исходя из ваших первоначальных рассуждений, Haskell выведет v :: forall a. Num a => a
v :: forall a. Num a => a
, по умолчанию v
на RHS набирает Integer
:
v :: forall a. Num a => a
v = fromIntegral (v :: Integer)
Но вместо этого он начинается с v :: a
. Поскольку v
передается fromIntegral
, оно налагает Integral a
. Наконец, он обобщает. a
В итоге программа оказывается
v :: forall a. Integral a => a
v = fromIntegral (v :: a)