Haskell - fmap fmap不起作用

时间:2011-04-29 21:18:38

标签: haskell types ghci

我正在使用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时,我得到了与上面相同的类型。

我做错了什么?尽管GHCi为它找到了一个类型,为什么fmap fmap会给出类型错误?

2 个答案:

答案 0 :(得分:7)

您似乎遇到了monomorphism restriction

使用-XNoMonomorphismRestriction在GHCi中尝试您的示例可以得到您期望的结果。

你也可以写let f x = fmap fmap $ x来颠覆这一点。单态限制仅适用于“看起来像”值的顶级定义,即f = something,因此引入显式参数会导致它不再适用。如果它不在顶层(例如在where子句中),它也不适用。有关详细信息,请参阅链接。

答案 1 :(得分:1)

我无法在任何地方发表评论所以我会发布一个答案。如前所述,您收到的错误是由于单态限制造成的。将类型签名修复到原始问题中给出的两个中的任何一个确实让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)