有时候我需要使用几个嵌套的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
,以模仿命令式编程中的MaybeT
和ExceptT
:
continue
但是,正如上面的代码所示,每次我需要在这个&#34;仿真循环&#34;中进行任何break
时,我需要在它之前加上一个丑陋的runExceptT . forM [1..] $ \ _ -> runMaybeT $ do
...
mzero -- this mimics continue
lift $ throwE "..." -- this mimics break
lift . lift $ putStrLn "Hello!"
...
。想象一下,如果我有更复杂的嵌套和许多IO
操作,这很快就变成了一种骚动。我如何使代码更清晰,更简洁?
答案 0 :(得分:6)
对于IO
的特定情况,您可以使用liftIO :: MonadIO m => IO a -> m a
通过任意深度的monad变换器堆栈解除IO
操作:
liftIO $ putStrLn "Hello"
此表达式的类型为MonadIO m => m ()
。在其中某处包含MonadIO
实例的任何转换器堆栈本身都应该有一个MonadIO
实例,这就是为什么这适用于任何深度的堆栈。