假设为了简单起见,我有以下monad变换器堆栈(r
和s
为()
),
newtype MyMonad m a = MM (ReaderT () (StateT () m a)
如果我想将它用作haskeline的InputT
的基础monad,我需要一个System.Console.Haskeline.MonadException
实例。鉴于apparent complexity这些实例,我宁愿让编译器使用GeneralizedNewtypeDeriving
为我推导出这个。具体来说,我希望以下内容可以进行类型检查,
{-# LANGUAGE GeneralizedNewtypeDeriving, StandaloneDeriving, FlexibleContexts #-}
import Control.Monad.State
import Control.Monad.Reader
import Control.Monad.IO.Class
import Control.Applicative
import System.Console.Haskeline.MonadException
newtype MyMonad m a = MM (ReaderT () (StateT () m) a)
deriving (Functor, Applicative, Monad, MonadIO)
deriving instance (MonadException m) => MonadException (MyMonad m)
但遗憾的是,这给了我,
/home/bgamari/hi.hs:11:1:
Could not deduce (MonadException (StateT () m))
arising from the superclasses of an instance declaration
from the context (MonadIO (MyMonad m), MonadException m)
bound by the instance declaration at /home/bgamari/hi.hs:11:1-66
Possible fix:
add an instance declaration for (MonadException (StateT () m))
In the instance declaration for `MonadException (MyMonad m)'
查看StateT
和ReaderT
提供的实例,
instance MonadException m => MonadException (ReaderT r m)
instance MonadException m => MonadException (StateT s m)
期望编译器推导出StateT
实例似乎是完全合理的。我是否期待过于狡猾GeneralizedNewtypeDeriving
?如何实现这个实例而不是开放编码呢?
答案 0 :(得分:5)
状态monad有两个版本:strict和lazy。 import Control.Monad.State
brings in the lazy version,但MonadException
的实例似乎是严格版本。
尝试使用import Control.Monad.State.Strict
代替import Control.Monad.State
。