Конкретный тип вывода с использованием функции uncurry
Я играл с 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 ответа
Это не имеет ничего общего с 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 #-}
).
В ghci есть магия, связанная с расширенными правилами по умолчанию. В основном, среди прочего, ограничения Num по умолчанию устанавливаются на ограничения типа Integer, а ограничения с плавающей точкой на Double, когда в противном случае возникнет ошибка (в данном случае из-за ограничения злого мономорфизма).