Псевдоним для имени функции имеет другую подпись типа. Зачем?

import Data.List (genericLength)

len = genericLength

:t genericLength
genericLength :: (Num i) => [b] -> i
:t len
len :: [b] -> Integer

Почему тип len отличается от типа genericLength? Целью здесь является использование более короткого псевдонима для genericLength.

Не являются ли функции первоклассными в haskell? Не следует ли указывать другое имя для функции в идентичной функции?

Ответ 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 Report. Я также упомянул, что GHC поддерживает расширенную форму дефолта, которая в основном используется для GHCi (и включена там по умолчанию), что иногда путает людей.