绑定其他monad m1中的monadic值(m2 a) [英] bind a monadic value (m2 a) inside some other monad m1
问题描述
在今天编码Dojo中,我尝试了下面的内容:
example :: IO()
example = do输入< - getLine
解析< - parseOnly解析器输入
...
其中 parseOnly :: Parser a - > String a
(来自 attoparsec
)当然编译器抱怨 Either ..
是而不是 IO ..
基本上告诉我我在混合单子。
当然这可以通过
case parseOnly parser input of .. - > ..
我认为这是不礼貌的。另外我的猜测是别人早些时候有这个问题,我认为这个解决方案与monad变形金刚有关,但最后一点我不能拼凑在一起。
它也提醒我 liftIO
- 但这是我想的另一种解决方法,它解决了解除周围monad内部发生的IO操作的问题(更确切地说, MonadIO
- 例如在 Snap
内部,当想要打印某些内容到 stdout
时,获取一些http )。
更常见的这个问题似乎是针对 Monad m1
和一个(不同的)<$ c $
示例=做一个< - m1Action
b< - m2Action
..
<一般来说,你不能。整个do块必须是一个特定的monad(因为示例
需要有一些特定的类型)。如果你可以绑定一个任意其他的monad,你可以使用 unsafePerformIO
。
Monad变换器允许你要生产一个monad,将多个其他monad可以做的事情组合起来。但是你必须决定do块中的所有操作都使用相同的monad变换堆栈来使用它们,它们不是一种在块中间任意切换monad的方式。$ /
Working in a Coding Dojo today I tried the following
example :: IO ()
example = do input <- getLine
parsed <- parseOnly parser input
...
where parseOnly :: Parser a -> Either String a
(from attoparsec
) of course the compiler complained that Either ..
is not IO ..
essentially telling me I am mixing monads.
Of course this can be solved by
case parseOnly parser input of .. -> ..
which is kind of unelegant, I think. Also my guess is that somebody else had this problem earlier and the solution I think is related to monad transformers, but the last bits I cannot piece together.
It also reminded me of liftIO
- but this is the other way around I think which solves the problem of lifting an IO action happening inside some surrounding monad (more precisely MonadIO
- say for example inside Snap
when one wants to print something to stdout
while getting some http).
More general this problem seems to be for a Monad m1
and a (different) Monad m2
how can I do something like
example = do a <- m1Action
b <- m2Action
..
You can't, in general. The whole do block has to be one specific monad (because example
needs to have some specific type). If you could bind an arbitrary other monad inside that do block, you'd have unsafePerformIO
.
Monad transformers allow you to produce one monad combining the kinds of things multiple other monads can do. But you have to decide that all the actions in your do block use the same monad transformer stack to use those, they're not a way to arbitrarily switch monads mid do-block.
Your solution with case
only works because you've got a particular known monad (Either) that has a way of extracting values from inside it. Not all monads provide this, so it's impossible to build a general solution without knowing the particular monads involved. That's why the do block syntax doesn't provide such a shortcut.
这篇关于绑定其他monad m1中的monadic值(m2 a)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!