#haskell #types
#haskell #типы
Вопрос:
import Data.List (genericLength)
len = genericLength
:t genericLength
genericLength :: (Num i) => [b] -> i
:t len
len :: [b] -> Integer
Почему тип len
отличается от типа genericLength
? Цель здесь состоит в том, чтобы использовать более короткий псевдоним для genericLength
.
Разве функции в haskell не первоклассные? Не должно ли присвоение другого имени функции приводить к идентичной функции?
Комментарии:
1. Я недостаточно знаю об этом, чтобы опубликовать ответ, но я почти уверен, что это как-то связано с ограничением мономорфизма . Если вы поместите
{-# LANGUAGE NoMonomorphismRestriction #-}
в начало файла, он будет вести себя так, как вы ожидаете.2. 1 Джеффри за высказывание, что это связано с ограничением мономорфизма.
Ответ №1:
То, что вы видите здесь, связано с требованием, чтобы объявления верхнего уровня без аргументов были мономорфными. Вы можете найти некоторое обсуждение причин этого в Haskell wiki, а также некоторую информацию о контроле этого поведения в руководстве пользователя GHC.
В качестве иллюстрации обратите внимание, что предоставление len
аргумента устраняет проблему:
len x = genericLength x
> :t len
len :: Num i => [b] -> i
Так же, как и присвоение ему подписи типа:
len :: (Num b) => [a] -> b
len = genericLength
То же самое относится и к отключению ограничения мономорфизма:
{-# LANGUAGE NoMonomorphismRestriction #-}
import Data.List (genericLength)
len = genericLength
> :t len
len :: Num i => [b] -> i
В этом конкретном случае, я думаю, вы также получаете другой тип (а не ошибку компилятора) из-за правил по умолчанию, которые указывают, что определенные классы типов должны по умолчанию использовать определенные типы (в данном случае, Num
по умолчанию Integer
. Если вы попытаетесь проделать то же самое с fmap
, вы получите это:
> :r
[1 of 1] Compiling Main ( MonoTest.hs, interpreted )
MonoTest.hs:4:5:
Ambiguous type variable `f0' in the constraint:
(Functor f0) arising from a use of `fmap'
Possible cause: the monomorphism restriction applied to the following:
f :: forall a b. (a -> b) -> f0 a -> f0 b
(bound at MonoTest.hs:4:1)
Probable fix: give these definition(s) an explicit type signature
or use -XNoMonomorphismRestriction
In the expression: fmap
In an equation for `f': f = fmap
Failed, modules loaded: none.
Вы можете найти некоторую информацию о дефолте в отчете Haskell 98. Я также упомяну, что GHC поддерживает расширенную форму дефолта, которая в основном используется для GHCi (и включена там по умолчанию), что иногда сбивает людей с толку.
Комментарии:
1. @gorlum0: Хахахаха, мономорфизм и дефолт, безусловно, делают эту функцию особенно бесполезной.
2. Обратите внимание, что это больше не должно происходить с GHC 7.8, поскольку «ограничение мономорфизма теперь отключено по умолчанию в GHCi». ( downloads.haskell.org /~ghc/7.8.1-rc1/docs/html/users_guide/… )