绑定其他monad m1中的monadic值(m2 a) [英] bind a monadic value (m2 a) inside some other monad m1

查看:109
本文介绍了绑定其他monad m1中的monadic值(m2 a)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在今天编码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的方式。$ /

case 的解决方案只能用,因为你有一个特定的monad(Either),它有一种从内部提取值的方法它。并非所有monad都提供此功能,因此如果不知道所涉及的特定monad,就无法构建一个通用解决方案。这就是为什么do block语法不提供这种快捷方式的原因。


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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆