广义Newtype导出

时间:2014-09-05 20:25:31

标签: haskell monads state-monad deriving newtype

Haskell可以在MonadState s下面的T1中派生T2的实例,但不能在T2中派生,但这是一个非常相似的类型。我应该以哪种方式修改MonadState s的代码,以便可以自动派生{-# LANGUAGE GeneralizedNewtypeDeriving #-} import Control.Monad.Reader import Control.Monad.State newtype T1 r s a = T1 { runT1 :: ReaderT r (State s) a } deriving (Monad, MonadReader r, MonadState s) newtype T2 r s a = T2 { runT2 :: StateT r (State s) a } deriving (Monad, MonadState r, MonadState s) 的实例?

{{1}}

1 个答案:

答案 0 :(得分:7)

你不能让一个类型有MonadState的两个实例。这是因为MonadState被定义为

class Monad m => MonadState s m | m -> s where
    get :: m s
    set :: s -> m ()
    state :: (s -> (a, s)) -> m a

关键部分是| m -> s。这需要扩展名FunctionalDependencies,并声明对于任何m,我们会自动知道相关的s。这意味着对于任何给定的ms只能有一个选项才有效。因此除非MonadState r m,否则您无法让MonadState s mr ~ s同时使用它。如果是r ~ s,那么编译器将如何知道它应用于哪个底层monad?在这种情况下,我认为如果您创建getput函数,使用后缀来指示哪些函数,getInnersetInner函数会更容易理解和使用代码,例如{{ 1}},getOutersetOuter,{{1}}。