Конкретный тип вывода с использованием функции uncurry - PullRequest
6 голосов
/ 15 февраля 2011

Я играл с функцией uncurry в GHCi, и я нашел что-то, чего совсем не смог получить.Когда я применяю uncurry к функции (+) и привязываю ее к некоторой переменной, как показано в коде ниже, компилятор делает вывод, что его тип специфичен для Integer:

Prelude> let add = uncurry (+)
Prelude> :t add
add :: (Integer, Integer) -> Integer

Однако, когда спрашиваетсядля типа следующего выражения я получаю (что я ожидаю) правильный результат:

Prelude> :t uncurry (+)
uncurry (+) :: (Num a) => (a, a) -> a

Что бы это вызвало?Это относится к GHCi?

То же самое относится к let add' = (+).

ПРИМЕЧАНИЕ. Я не смог воспроизвести это с использованием скомпилированного файла .

Ответы [ 2 ]

21 голосов
/ 15 февраля 2011

Это не имеет ничего общего с ghci. Это ограничение мономорфизма, являющееся раздражающим. Если вы попытаетесь скомпилировать следующий файл:

add = uncurry (+)
main = do
    print $ add (1,2 :: Int)
    print $ add (1,2 :: Double)

Вы получите ошибку. Если развернуть:

main = do
    print $ uncurry (+) (1,2 :: Int)
    print $ uncurry (+) (1,2 :: Double)

Все хорошо, как и ожидалось. Ограничение мономорфизма отказывается сделать что-то, что «выглядит как значение» (то есть определено без аргументов в левой части от равенства), типа полиморфного типа, потому что это повредит кэшированию, которое обычно происходит. Например.

foo :: Integer
foo = expensive computation

bar :: (Num a) => a
bar = expensive computation

foo гарантированно рассчитывается только один раз (ну, по крайней мере, в GHC), тогда как bar будет вычисляться каждый раз, когда он упоминается. Ограничение мономорфизма направлено на то, чтобы спасти вас от второго случая, если по умолчанию использовать первый, когда кажется, что это то, что вы хотели.

Если вы используете функцию только один раз (или всегда в одном и том же типе), вывод типа позаботится о том, чтобы вывести правильный тип для вас. В этом случае ghci делает что-то немного другое, угадывая раньше. Но использование его в двух разных типах показывает, что происходит.

В случае сомнений используйте сигнатуру типа (или отключите убогую вещь с помощью {-# LANGUAGE NoMonomorphismRestriction #-}).

4 голосов
/ 15 февраля 2011

В расширенных правилах по умолчанию используется ghci.В основном, среди прочего, ограничения Num по умолчанию устанавливаются на ограничения типа Integer, а ограничения с плавающей точкой - на Double, когда в противном случае возникнет ошибка (в данном случае из-за ограничения злого мономорфизма).

...