在一些其他monad m1中绑定一个monadic值(m2 a)

eps*_*lbe 2 monads haskell monad-transformers

今天在Coding Dojo工作,我尝试了以下方法

example :: IO ()
example = do input <- getLine
             parsed <- parseOnly parser input
             ...
Run Code Online (Sandbox Code Playgroud)

其中,parseOnly :: Parser a -> Either String a(从attoparsec课程)编译器抱怨说,Either ..没有IO ..实质上是告诉我,我混的单子.

当然这可以通过解决

             case parseOnly parser input of .. -> ..
Run Code Online (Sandbox Code Playgroud)

我想,这有点不雅观.另外我的猜测是其他人之前遇到过这个问题而且我认为解决方案与monad变换器有关,但最后一点我不能拼凑在一起.

它也让我想起了liftIO- 但这是另一种方式,我认为这解决了在一些周围的monad中发生IO动作的问题(更确切地说MonadIO- 例如在内部,Snap当一个人想要stdout在获取一些http 时打印一些东西).

更一般的这个问题似乎是针对a Monad m1和a(不同)Monad m2我该怎样做的事情

example = do a <- m1Action
             b <- m2Action
             ..
Run Code Online (Sandbox Code Playgroud)

Ben*_*Ben 6

一般来说,你不能.整个do块必须是一个特定的monad(因为example需要一些特定的类型).如果你可以绑定任何其他monad里面的那个块,你就可以了unsafePerformIO.

Monad变形金刚允许你制作一个monad,结合多个其他monad可以做的事情.但是你必须决定do块中的所有动作都使用相同的monad变换器堆栈来使用它们,它们不是在do-block中任意切换monad的方法.

你的解决方案case只有作用,因为你有一个特定的已知monad(Either),它有一种从里面提取值的方法.并非所有monad都提供此功能,因此在不了解所涉及的特定monad的情况下构建通用解决方案是不可能的.这就是do块语法不能提供这种快捷方式的原因.