假设我在GHCi 7.6.3中定义了一个函数
> let fstM xs = ((=<<) (return . fst)) xs
> :t fstM
fstM :: Monad m => m (b, b1) -> m b
> fstM [(1,2), (3,4)]
[1,3]
> fstM (Just (1,2))
Just 1
这不是一个令人兴奋的功能;它基本上只是liftM fst
。但是,如果我尝试以无点样式定义它,我会收到以下错误:
> let fstM = ((=<<) (return . fst))
<interactive>:8:13:
No instance for (Monad m0) arising from a use of `=<<'
The type variable `m0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Monad ((->) r) -- Defined in `GHC.Base'
instance Monad IO -- Defined in `GHC.Base'
instance Monad [] -- Defined in `GHC.Base'
...plus two others
In the expression: ((=<<) (return . fst))
In an equation for `fstM': fstM = ((=<<) (return . fst))
表达本身似乎很好
> :t ((=<<) (return . fst))
((=<<) (return . fst)) :: Monad m => m (b, b1) -> m b
但试图给它命名失败。
显然我的理解存在差距;我不知道第一个定义如何推断出类型约束,而第二个定义则表明它是模棱两可的。也就是说,我知道我可以写
fstM :: Monad m => m (a, b) -> m a
fstM = ((=<<) (return . fst))
解决歧义,但是看似不必要的参数使得类型声明变得不必要有什么特别的呢?