Смущает преобразование WHNF в NF в Haskell
В простом примере преобразование WHNF в NF с помощью печати работает нормально
Prelude> let x = 1 + 2 :: Int
Prelude> :sprint x
x = _
Prelude> x
3
Prelude> :sprint x
x = 3
Но в случае, тип не объявлен, он не работает.
Prelude> let x = 1 + 2
Prelude> :sprint x
x = _
Prelude> x
3
Prelude> :sprint x
x = _
Не могли бы вы объяснить, почему конвертация не работает в последнем случае?
1 ответ
Поскольку в GHCi ограничение мономорфизма отключено, последнее x
это полиморфное значение типа x :: Num a => a
, Так что это не просто целое число, а своего рода функция DictNum a -> a
который готов создать значение в любом числовом типе.
В самом деле, x :: Int, x :: Float, x :: Double
будет работать и производить разные значения. Эти значения численно одинаковы, но вычислительно различны, так как они являются представлениями в разных типах.
поскольку x
по сути, это "множественные значения, сгенерированные по требованию", здесь нет ни одного WHNF или NF.
Обратите внимание, что если мы вычисляем (x :: Int) + (x :: Int)
, затем x
пересчитывается дважды: GHC в общем случае не будет "кэшировать" WHNF по типу Int
для последовательных вычислений. Это похоже на f 3 + f 3
, где f 3
не кэшируется (запоминается).
Это двойное вычисление - именно то, чего пытается избежать ограничение мономорфизма.