有没有比在嵌套的`MonadTrans`中每个'IO`之前写`lift`s更好的方法?

时间:2015-10-15 03:16:26

标签: haskell monad-transformers

有时候我需要使用几个嵌套的public class IntStackList{ private StackNode head; public IntStackList(){ this.head = null; } public void push(int value){ this.head = new StackNode(value, head); } public int pop(){ int value = this.head.getValue(); //get the int value stored in the head node this.head = head.getLink(); //sets the head to the next node in line return value; } } 。例如,我会在sed -e 's/></>\n</g' file.txt > output.txt 内放置一个MonadTrans,以模仿命令式编程中的MaybeTExceptT

continue

但是,正如上面的代码所示,每次我需要在这个&#34;仿真循环&#34;中进行任何break时,我需要在它之前加上一个丑陋的runExceptT . forM [1..] $ \ _ -> runMaybeT $ do ... mzero -- this mimics continue lift $ throwE "..." -- this mimics break lift . lift $ putStrLn "Hello!" ... 。想象一下,如果我有更复杂的嵌套和许多IO操作,这很快就变成了一种骚动。我如何使代码更清晰,更简洁?

1 个答案:

答案 0 :(得分:6)

对于IO的特定情况,您可以使用liftIO :: MonadIO m => IO a -> m a通过任意深度的monad变换器堆栈解除IO操作:

liftIO $ putStrLn "Hello"

此表达式的类型为MonadIO m => m ()。在其中某处包含MonadIO实例的任何转换器堆栈本身都应该有一个MonadIO实例,这就是为什么这适用于任何深度的堆栈。