我今天在Haskell遇到了一件令人沮喪的東西。Haskell let-expression中的奇怪類型錯誤 - 問題是什麼?
這裏發生了什麼:
- 我寫在ghci中的功能,並給它一個類型簽名
- ghci的抱怨型
- 我刪除了類型簽名
- ghci的接受功能
- 我檢查了推斷類型
- 推斷類型與我試圖給它的類型完全相同
- 我很心疼
- 我發現我可以重現該問題在任何鬆懈表達
- 咬牙切齒的;決定在SO
嘗試與專家進行磋商,以與類型簽名定義函數:
Prelude Control.Monad> let myFilterM f m = do {x <- m; guard (f x); return x} :: (MonadPlus m) => (b -> Bool) -> m b -> m b
<interactive>:1:20:
Inferred type is less polymorphic than expected
Quantified type variable `b' is mentioned in the environment:
m :: (b -> Bool) -> m b -> m b (bound at <interactive>:1:16)
f :: (m b -> m b) -> Bool (bound at <interactive>:1:14)
Quantified type variable `m' is mentioned in the environment:
m :: (b -> Bool) -> m b -> m b (bound at <interactive>:1:16)
f :: (m b -> m b) -> Bool (bound at <interactive>:1:14)
In the expression:
do { x <- m;
guard (f x);
return x } ::
(MonadPlus m) => (b -> Bool) -> m b -> m b
In the definition of `myFilterM':
myFilterM f m
= do { x <- m;
guard (f x);
return x } ::
(MonadPlus m) => (b -> Bool) -> m b -> m b
中定義的功能沒有類型簽名,檢查推斷的類型:
Prelude Control.Monad> let myFilterM f m = do {x <- m; guard (f x); return x}
Prelude Control.Monad> :t myFilterM
myFilterM :: (MonadPlus m) => (b -> Bool) -> m b -> m b
用於極大的利好作用 - 一切正常:
Prelude Control.Monad> myFilterM (>3) (Just 4)
Just 4
Prelude Control.Monad> myFilterM (>3) (Just 3)
Nothing
我最好的猜測,這是怎麼回事:
類型註釋不知何故沒有很好地讓表達式工作,當有一個do-block的時候。
獎勵積分:
是有標準的Haskell分佈做了這樣的功能?我很驚訝,filterM
做了非常不同的事情。
類型註釋適用於定義的RHS,而不是'myFilterM',所以你應該說'::(MonadPlus m)=> m b'。這就是爲什麼錯誤信息中'm'和'f'的類型很奇怪。但是我仍然得到了「推斷類型的多態性比預期的更少」的錯誤信息(雖然有更明智的類型),我不知道是什麼原因造成的。 – dave4420
@ dave4420你也使用GHC 6. *?他們在GHC 7中編寫了一個新的類型推斷引擎;也許這是一個錯誤。 – fuz
@FUZxxl那是GHC 6.12.1。我剛剛用GHC 7.0.3試了一下,我得到了兩條錯誤消息,而不是一條,都沒有提到多態性。可能是GHC 7拒絕推斷'myFilterM'的參數類型。 – dave4420