在用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