您是否已经看过以下功能?这叫什么?它有用的是什么?是否可以比StateT
更为一般地定义?
simpleFunction (StateT f) = StateT $ (\s -> return (f s, s))
顺便说一下,ghc给它类型Monad n => StateT s m a -> StateT s n (m (a, s))
。
还有另一种定义:
simpleFunction m = do
s <- get
mapStateT (\l -> return (l, s)) m
答案 0 :(得分:1)
像n (m a)
这样的两个monad通常非常有用(组合可能不是monad等)。所以我想更多可用的版本将是类型
(Monad m) => StateT s m a -> StateT s m (a, s)
。
这可以推广到m
上的任意状态变换器:
import Control.Monad
import Control.Monad.State
f1 :: (MonadState s (t m), MonadTrans t, Monad m) => StateT s m a -> t m (a, s)
f1 (StateT f) = get >>= lift . f
由于我们唯一需要的是get
,我们可以进一步概括为:
f2 :: (MonadTrans t, Monad m, Monad (t m)) => t m s -> StateT s m a -> t m (a, s)
f2 g (StateT f) = g >>= lift . f
如果你真的需要两个monad,或许MFunctor
会很有用 - 像hoist
或generalize
这样的函数允许在monad之间切换。
答案 1 :(得分:0)
simpleFunction结构通过两个参数化:StateT monad和函数f。正如两个给定定义中所示,simpleFunction从monad的内部获取状态,然后使用给定函数映射计算的返回值和最终状态。
按照一个非常简单的例子来看一个有效的例子:
import Control.Monad.State
inc :: State Int Int
inc = do
n <- get
put (n + 1)
return n
simpleFunction = do
s <- get
mapState (\l -> (l,s)) inc
main = do
print $ runState simpleFunction 1
结果是:((1,2),1)这是((返回值,最终状态),初始状态)
你看到的simpleFunction并不复杂。它可以与StateT以外的monad一起使用。在这种情况下,您必须实现自己的地图并获得。
希望它有用!