假设我有一个IO Int
包裹在一个StateT MyState
,那么我的值为State MyState Int
我想在堆叠单子中使用它。我如何在这种内在的意义上提升它?我已经知道使用lift
or liftIO
如果我得到与内部兼容的东西,我只需要提升到外部单子,但现在我遇到了相反的问题:该值已经在外部单子中,但不在内部单子中。
例如:
checkSame :: State MyState a -> IO a -> StateT MyState IO Bool
checkSame sim real = do
rres <- liftIO real
sres <- ??? sim
return $ rres == sres
我是否必须“获取”状态,手动将其推入 runState 并再次将其全部装箱,或者是否有某种通用方法可以做到这一点?
顺便说一句,那个 sim 参数是一大堆与 IO 无关的有状态函数,所以我有点不愿意让它们全部返回StateT MyState IO a
如果我能避免的话。
您有两个选择:
- 找到一个单子态射。这通常是找到合适的库的问题;在这种情况下hoist and 概括在一起应该可以带你到达你需要去的地方。
-
做你的State
动作更加多态。这是常用的,也是推荐的;这相当于预先应用第 1 部分中的态射,但是已经在其中部署了很多机制mtl
库以使其变得简单。这里的想法是,如果你写你的State
行动只是在get
, put
, and modify
,然后代替类型State s a
,你可以给它指定类型:
MonadState s m => m a
然后,在调用站点,您可以选择适合于此的任何 monad,包括State s a
and StateT s IO a
。此外,由于它专门针对该类型State s a
,你可以确定它不会做任何事情IO
或类似的东西State s a
本身做不到,所以你得到同样的行为保证。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)