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

#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/… )