首页 > 解决方案 > 如何使用 StateT、ContT 和 ReaderT 创建 monad?

问题描述

如何创建一个使用 State、Cont 和 Reader 转换器的 monad?我想阅读一个环境,并更新/使用状态。但是,我也想暂停/中断动作。例如,如果满足某个条件,则状态保持不变。

到目前为止,我有一个使用 ReaderT 和 StateT 的 monad,但我无法弄清楚如何包含 ContT:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Test where
-- monads
import   Data.Functor.Identity (Identity, runIdentity)
import   Control.Monad.State
import   Control.Monad.Reader
import   Control.Monad.Cont

-- reader environment
type In = Integer

-- cont: if true then pause, else continue 
type Pause = Bool

-- state environment:
newtype StateType = StateType { s :: Integer }

newtype M r = M {_unM :: ReaderT In (ContT Pause (StateT StateType Identity)) r}
  deriving ( Functor, Applicative, Monad
           , MonadReader In
           , MonadCont   Pause
           , MonadState  StateType
           )

-- run monadic action
runM :: In -> Pause -> StateType -> M r -> StateType
runM inp pause initial act
  = runIdentity             -- unwrap identity
  $ flip execStateT initial -- unwrap state
  $ flip runContT   pause   -- unwrap cont
  $ flip runReaderT inp     -- unwrap reader
  $ _unM act                -- unwrap action

这给出了错误:

* Expected kind `* -> *', but `Pause' has kind `*'
* In the first argument of `MonadCont', namely `Pause'
  In the newtype declaration for `M'
  |
24|         , MonadCont  Pause
  |

好的,但是为什么Pause需要 kind * -> *?...我淹没在类型中,需要解释。Pause必须采取什么形式,一个功能?ContT 如何整合?最终,我计划将 Cont 用于控制结构。

标签: haskellmonadsmonad-transformerscontinuations

解决方案


MonadReaderand不同MonadStateMonadCont类型类只接受一个参数。由于该参数m必须是 a Monad,因此它必须具有 kind * -> *

在您的派生子句中,您MonadCont,不希望MonadCont Pause.

在回答后续问题时添加:

ContT 定义为:

newtype ContT r m a = ContT { runContT :: (a -> m r) -> m r }

请注意,r在您的定义中的newtype M r是作为 final ( a) 参数传递给ContT. 插入变量,你有

ContT Bool (State StateType) a = ContT { 
    runContT :: (a -> State StateType Bool) -> (State StateType Bool)
  }

这提供了一个计算上下文,您可以在其中操作StateType, 并使用定界延续。最终,您将构建一个ContT Bool (State StateType) Bool. 然后您可以运行延续(使用evalContT),并返回到更简单的State StateType上下文。(实际上,您可以在程序的同一部分中解开所有 3 个 monad 转换器。)


推荐阅读