提起以修复单体变压器堆叠的*内部* [英] Lift to fix the *inside* of a monad transformer stack
问题描述
StateT MyState
中的 IO Int
,那么我的值为 State MyState Int
,我想在堆叠monad中使用它。如何从内在意义上解除它?我已经知道要使用 lift
或 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
,如果我可以避免的话。
- 找到单态射线。这通常是找到合适的图书馆的问题;在这种情况下,提升和概括一起应该让你去你需要去的地方。 让你的
- Find a monad morphism. This is often a matter of finding the right library; in this case hoist and generalize together should get you where you need to go.
Make your
State
action more polymorphic. This is the commonly used one, and the recommended one; it amounts to pre-applying the morphism from part 1, but has a lot of machinery put in place already in themtl
library to make it easy. The idea here is that if you write yourState
action just in terms ofget
,put
, andmodify
, then instead of the typeState s a
, you can give it the type:MonadState s m => m a
Then later, at the call site, you can choose whatever monad is appropriate for this, including both
State s a
andStateT s IO a
. Moreover, since it specializes to the typeState s a
, you can be sure it doesn't do anyIO
or anything like that thatState s a
itself couldn't do, so you get the same behavioral guarantees.
状态
动作更具多态性。这是常用的和推荐的;它相当于预先应用第1部分的态射,但是已经在 mtl
库中放置了大量机制,以方便使用。这里的想法是,如果你只用 get
,来编写你的 State
操作,put
和修改
,然后而不是类型 State sa
,您可以给它键入: MonadState sm => ma
然后,在呼叫站点,您可以选择适合的monad,包括两个 Suppose I have an For instance: Do I have to 'get' the state, shove it through runState by hand and box it all up again, or is there some generic way to do this? BTW, that sim parameter is a whole bunch of stateful functions that have nothing to do with IO, so I'm a bit reluctant to make them all return You have two options:
这篇关于提起以修复单体变压器堆叠的*内部*的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! State sa
和 StateT s IO a
。此外,由于它专注于 State sa
类型,因此您可以确定它不会执行任何 IO
或任何其他任何操作就像IO Int
wrapped in a StateT MyState
, then I have a value of State MyState Int
which I want to use in the stacked monad. How do I lift it in this inner sense? I already know to use lift
or liftIO
if I get something compatible with the inside that I just need to lift to the outside monad, but now I have the opposite problem: the value is already in the outer monad but not the inner one. checkSame :: State MyState a -> IO a -> StateT MyState IO Bool
checkSame sim real = do
rres <- liftIO real
sres <- ??? sim
return $ rres == sres
StateT MyState IO a
if I can avoid it.