今天我在 Haskell 中遇到了一件令人沮丧的事情。
这是发生的事情:
- 我在 ghci 中写了一个函数并给它一个类型签名
- ghci 抱怨类型
- 我删除了类型签名
- ghci 接受了这个功能
- 我检查了推断的类型
- 推断的类型与我尝试给出的类型完全相同
- 我很苦恼
- 我发现我可以在任何 let-expression 中重现该问题
- 咬牙切齿; 决定咨询 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 时,类型注释不知何故不适用于 let-expressions。
对于奖励积分:
标准 Haskell 发行版中是否有这样做的功能?我很惊讶它filterM
做了一些非常不同的事情。