【发布时间】:2011-12-01 13:16:27
【问题描述】:
我今天在 Haskell 中遇到了一件令人沮丧的事情。
事情是这样的:
- 我在 ghci 中写了一个函数并给它一个类型签名
- ghci 抱怨类型
- 我删除了类型签名
- ghci 接受了函数
- 我检查了推断的类型
- 推断的类型与我尝试给出的类型完全相同
- 我很苦恼
- 我发现我可以在任何 let 表达式中重现该问题
- 咬牙切齿;决定咨询 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 块时,类型注释不知何故不适用于 let 表达式。
奖励积分:
标准 Haskell 发行版中是否有执行此操作的函数?我很惊讶filterM 做了一些非常不同的事情。
【问题讨论】:
-
类型注释适用于定义的RHS,而不是
myFilterM,所以你应该说:: (MonadPlus m) => m b。这就是为什么您的错误消息中m和f的类型如此奇怪的原因。但我仍然收到“推断类型的多态性低于预期”错误消息(尽管类型更合理),我不知道是什么原因造成的。 -
@dave4420 你也使用 GHC 6.* 吗?他们在 GHC 7 中编写了一个新的类型推理引擎;也许这是一个错误。
-
@FUZxxl 那是 GHC 6.12.1。我刚刚用 GHC 7.0.3 尝试过,我收到两条错误消息而不是一条,它们都没有提到多态性。可能是 GHC 7 拒绝推断
myFilterM的参数类型。
标签: haskell types type-inference let