在用monad变换器构建monad堆栈来编写库时,我遇到了一个关于它的行为的问题。为什么此代码需要Monad约束?
下面的代码将无法通过类型检查:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Foo (FooM, runFooM, foo) where
import Control.Applicative
import Control.Monad.Reader
newtype FooM m a = FooM { runFooM :: ReaderT Int m a }
deriving (Functor, Applicative, Monad, MonadReader Int)
foo :: FooM m Int
foo = do
x <- ask
return x
的错误是:
$ ghc foo.hs
[1 of 1] Compiling Foo (foo.hs, foo.o)
foo.hs:12:3:
No instance for (Monad m) arising from a do statement
Possible fix:
add (Monad m) to the context of
the type signature for foo :: FooM m Int
In a stmt of a 'do' block: x <- ask
In the expression:
do { x <- ask;
return x }
In an equation for ‘foo’:
foo
= do { x <- ask;
return x }
解决方法是容易的GHC所暗示的,只是增加了Monad
约束到foo
功能:
foo :: Monad m => FooM m Int
foo = do
x <- ask
return x
但是在这里,foo
有趣只有ask
s的FooM
值赋予它的Int
值,它已经是一个(自动派生的)MonadReader
实例。 所以我认为Monad
约束是不需要m
。
我想这涉及到monad变压器(我使用mlt==2.2.1), 的实施,但我无法弄清楚确切的原因。 虽然我可能会错过某些明显的东西。 你能解释为什么这不通过检查?
谢谢。
啊!这是我错过的答案。非常感谢你! – bicycle1885 2014-09-01 14:31:11