Haskell - fmap fmap не работает - PullRequest
       25

Haskell - fmap fmap не работает

5 голосов
/ 30 апреля 2011

Я использую GHCi (версия 6.12.3), чтобы немного поиграть с Haskell.Недавно я читал о функторах и аппликативных функторах, которые думали, что если вы не могли бы реализовать нечто подобное <*> аппликативных функторов, используя только примитивы функтора.После некоторых размышлений я придумал fmap fmap, который имел бы (почти) идеальный тип

Functor f => f (a -> b) -> f (f a -> f b) или более обобщенно

(Functor f1, Functor f2) => f1 (a -> b) -> f1 (f2 a -> f2 b)

Я пытался

let q = fmap fmap

Я получил следующую ошибку

<interactive>:1:8:
    Ambiguous type variable `f1' in the constraint:
      `Functor f1' arising from a use of `fmap' at <interactive>:1:8-16
    Probable fix: add a type signature that fixes these type variable(s)

<interactive>:1:13:
    Ambiguous type variable `f' in the constraint:
      `Functor f' arising from a use of `fmap' at <interactive>:1:13-16
    Probable fix: add a type signature that fixes these type variable(s)

Запись вышеуказанной сигнатуры типа в соответствии с предложением не помогла.Сумасшедшая вещь, когда я набрал :t fmap fmap Я получил эквивалентный тип, как указано выше.

Что я делаю не так?Почему fmap fmap выдает ошибку типа, хотя GHCi находит для нее тип?

Ответы [ 2 ]

7 голосов
/ 30 апреля 2011

Похоже, вы сталкиваетесь с ограничением мономорфизма .

Попытка примера в GHCi с -XNoMonomorphismRestriction дает ожидаемый результат.

Вы также можете подорватьэто написав let f x = fmap fmap $ x.Ограничение мономорфизма применяется только к определениям верхнего уровня, которые «выглядят как» значения, то есть f = something, поэтому введение явного аргумента приводит к тому, что оно больше не применяется.Это также не будет применяться, если это не на верхнем уровне (например, в предложении where).Для получения более подробной информации см. Ссылку.

1 голос
/ 30 апреля 2011

Я пока не могу комментировать, поэтому выложу ответ.Как упоминалось ранее, ошибка, которую вы получаете, связана с ограничением мономорфизма.Фиксация сигнатуры типа к любому из двух приведенных в исходном вопросе действительно делает ghci счастливым, как вы и надеялись, может быть, вы просто немного ошиблись в синтаксисе?

Prelude> let q :: (Functor f) => f (a -> b) -> f (f a -> f b); q = fmap fmap
Prelude> :t q
q :: (Functor f) => f (a -> b) -> f (f a -> f b)

Prelude> let q :: (Functor f1, Functor f2) => f1 (a -> b) -> f1 (f2 a -> f2 b); q = fmap fmap
Prelude> :t q
q :: (Functor f1, Functor f2) => f1 (a -> b) -> f1 (f2 a -> f2 b)
...