所以我最近一直在关注状态monad,因为我想在haskell中构建一个解析器组合库。
我遇到了一个名为MonadState的类型类,我想知道这个类型类的重点是什么,你会在哪里使用它?
答案 0 :(得分:2)
MonadState
抽象出get
和put
函数,这样它们不仅可以用于一种类型,还可用于任何类型的函数,它们可以充当状态单子。它主要是为了使monad变换器工作。
不要过多详细说明,让我们假设您知道StateT
存在:它需要一个monad并返回一个可以充当状态的新monad。 (我会忽略懒惰和严格状态monad之间的区别)。然后可以通过将StateT
应用于Identity
monad来定义处理状态的monad:
newtype State s = StateT s Identity
只要输入类型是monad,我们就可以为MonadState
返回的monad提供StateT
实例:
-- Add state to any monad
instance Monad m => MonadState s (StateT s m) where
...
这表示将StateT
应用于任何 monad(不仅仅是Identity
)会产生一个可被视为状态monad的monad。
此外,您可以说包装状态monad的任何内容也是状态monad,只要它实现MonadState
:
-- Add Maybe to a state monad, it's still a state monad
instance MonadState s m => MonadState s (MaybeT m) where
...
-- Add Writer to a state monad, it's still a state monad
instance (Monoid w, MonadState s m) => MonadState s (WriterT w m) where
...
答案 1 :(得分:0)
MonadState
抽象状态monad(好像这些东西不够抽象,对吧?)。我们可以提供适当的State
和Monad
函数,而不是要求具有Monad
实例的具体类型get
,它允许我们使用我们喜欢的任何put
。特别是,我们可以使用StateT
来组合效果。
组合State和IO的简单示例:
tick :: (MonadIO m, MonadState Int m) => m ()
tick = do
x <- get
liftIO $ putStrLn ("incrementing " ++ (show x))
put (x+1)
> runStateT (tick >> tick >> tick >> tick) 5
incrementing 5
incrementing 6
incrementing 7
incrementing 8
((),9)