2011-04-29 60 views
5

我使用GHCi(版本6.12.3)與Haskell玩了一下。我最近閱讀了有關函數和應用函數的想法,認爲如果你不能使用函子的基元來實現應用函子的類似<*>。經過一番思考,我想出了fmap fmap這將有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會出現類型錯誤?

回答

7

看起來像是碰到了monomorphism restriction

在GHCi中試用您的示例-XNoMonomorphismRestriction可以得出您的預期結果。

你也可以通過編寫let f x = fmap fmap $ x來顛覆這一點。單態限制僅適用於「看起來像」值的頂級定義,即f = something,因此引入顯式參數會導致其不再適用。如果這不是最高級別(例如在where子句中),它也不適用。有關更多詳細信息,請參閱鏈接。

+1

它似乎是monomophism限制,因爲你的靈魂工程。謝謝。但是爲什麼當我指定類型時它不工作? – Mafi 2011-04-30 09:50:54

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) 
+0

是的,我剛剛得到了錯誤的語法。謝謝 – Mafi 2011-04-30 15:26:34