如果我们有以下两个函数,加法和减法,很容易将它们链接起来以对输入运行一系列计算:
add :: Int -> State Int ()
add n = state $ \x -> ((),x+n)
subtract :: Int -> State Int ()
subtract n = state $ \x -> ((),x-n)
manyOperations :: State Int ()
manyOperations = do
add 2
subtract 3
add 5
--etc
result = execState manyOperations 5
--result is 9
如果我们想在每次计算完成后打印出状态,我们使用StateT
monad 转换器:
add :: Int -> StateT Int IO ()
add n = StateT $ \x -> print (x+n) >> return ((),x+n)
subtract :: Int -> StateT Int IO ()
subtract n = StateT $ \x -> print (x-n) >> return ((),x-n)
manyOperations :: StateT Int IO ()
manyOperations = do
add 2
subtract 3
add 5
main = runStateT manyOperations 5
-- prints 7, then 4, then 9
StateT
是否可以在没有或任何自定义数据类型的情况下复制这种“组合计算和打印” ?
据我所知,MaybeT IO a
可以使用 using 执行所有可以执行的过程IO (Maybe a)
,但这似乎是因为它只是嵌套的 monad。另一方面,StateT
可能没有替代方案,因为s -> (a,s)
与s -> m (a,s)
我只能看到代码的两个方向:使用State Int (IO ())
or IO (State Int ())
,但考虑到实现StateT
我相信这是不可能的。我对么?
注意:我知道这完全不切实际,但是经过几个小时的工作后我找不到任何解决方案,这意味着我是正确的,或者我的技能不足以完成这项任务。