Как работает вычисление в Haskell для выражений с ограничениями

Предположим, я пишу в GHCi:

GHCi> let x = 1 + 2 :: Integer
GHCi> seq x ()
GHCi> :sprint x

GHCi печатает x = 3 как и ожидалось.

Однако,

GHCi> let x = 1 + 2
GHCi> seq x ()
GHCi> :sprint x

дает x = _

Единственная разница между двумя выражениями заключается в их типах (Integer против Num a => a). Мой вопрос в том, что именно происходит, и почему, по-видимому, x не оценивается в последнем примере.


person Matei    schedule 01.04.2020    source источник


Ответы (1)


Основная проблема в том, что

let x = 1 + 2

определяет полиморфное значение типа forall a. Num a => a, которое вычисляется подобно функции.

Каждое использование x может быть выполнено в другом типе, например. x :: Int, x :: Integer, x :: Double и так далее. Эти результаты никоим образом не "кэшируются", а пересчитываются каждый раз, как если бы x была функцией, которая, так сказать, вызывается несколько раз.

Действительно, обычная реализация классов типов реализует такой полиморфный x как функцию.

x :: NumDict a -> a

где приведенный выше аргумент NumDict a добавляется компилятором автоматически и содержит информацию о том, что a является типом Num, в том числе о том, как выполнять сложение, как интерпретировать целочисленные литералы внутри a и так далее. Это называется реализацией "передачи словаря".

Таким образом, многократное использование полиморфного x действительно соответствует многократному вызову функции, что приводит к повторному вычислению. Чтобы избежать этого, в Haskell было введено (ужасное) ограничение мономорфизма, заставляющее x вместо этого быть мономорфным. MR не является идеальным решением и в некоторых случаях может привести к неожиданным ошибкам типов.

Чтобы решить эту проблему, MR по умолчанию отключен в GHCi, поскольку в GHCi мы не особо заботимся о производительности — там важнее удобство использования. Однако это приводит к тому, что пересчет снова появляется, как вы обнаружили.

person chi    schedule 01.04.2020
comment
Думаю, стоило бы упомянуть о передаче словаря. - person Joseph Sible-Reinstate Monica; 02.04.2020