【发布时间】:2014-08-29 10:21:57
【问题描述】:
在使用 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 函数只有 asks 的 FooM 值来赋予其 Int 值,并且它已经是(自动派生的)MonadReader 实例。
所以我认为Monad 约束不需要m。
我猜这与 monad 转换器的实现有关(我使用 mlt==2.2.1), 但我无法弄清楚确切的原因。 不过,我可能会错过一些明显的东西。 你能解释一下为什么这没有通过检查器吗?
谢谢。
【问题讨论】:
标签: haskell