Here&#39;s some code I wrote the other day:<br><br><span style="font-family: courier new,monospace;">hasCycle :: (Applicative m, MonadIO m) =&gt; Node -&gt; m Bool</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">hasCycle n0 = runContT (<u>callCC</u> go) return</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> †where</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> † go <u>abort</u> = do visit [] IM.empty n0</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> † † † † † † † † return False</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> † † where</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> † † † visit preds h n = do</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> † † † † nid &lt;- nodeId n</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> † † † † h&#39; &lt;- foldM (\h&#39; n&#39; -&gt; do</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> † † † † † † † † † †n&#39;id &lt;- nodeId n&#39;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> † † † † † † † † † †case IM.lookup n&#39;id h&#39; of</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> † † † † † † † † † † †Just True -&gt; <u>abort</u> True</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> † † † † † † † † † † †Just False -&gt; return h&#39;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> † † † † † † † † † † †Nothing -&gt; visit (n:preds) h n&#39;)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> † † † † † † † † (IM.insert nid True h) =&lt;&lt; nodeChildren n</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> † † † † return (IM.insert nid False h&#39;)</span><br>
<br>This function returns True if the graph starting at n0 has cycles.† You can ignore the details; take a look at the use of &quot;abort&quot;.† The type of &quot;abort&quot; is <span style="font-family: courier new,monospace;">Bool -&gt; m (IM.IntMap Bool)</span> but the result type is actually irrelevant since this function will never return.† The effect of calling &quot;abort&quot; is to: jump back to the place where we called callCC and replace the call with the value we passed to &quot;abort&quot;.<br>
<br>You can think of callCC of creating a snapshot of the program&#39;s current execution state.† This snapshot (called the &quot;current continuation&quot;) is passed to the function that was the argument to &quot;callCC&quot; (&quot;go&quot; in the above).† This snapshot is represented as a function and you can call it.<br>
<br>If you call the continuation, two things happen:<br>†<br>†1. The currently executed code is aborted.<br>†2. The execution jumps back to the state in which callCC was called and the call to callCC gets replaced by the value you passed to the continuation.<br>
<br>Naturally, we cannot undo IO effects, so not all of the state is reset.† Also, since callCC is only available in the monad, it only saves the snapshot up to the closest &quot;runContT&quot;.<br><br>Another, more mind-bending feature of continuations is that you can store them and invoke them <i>multiple times</i>.† But that is a story for another day.<br>
<br>HTH<br><br>2009/7/4 GŁnther Schmidt &lt;<a href="mailto:gue.schmidt@web.de">gue.schmidt@web.de</a>&gt;:<br>&gt;<br>&gt; Hi,<br>&gt;<br>&gt; I&#39;ve got an IO action, some file system IO, traversing one level only and<br>
&gt; iterating over files found. I wish to build in an &quot;early&quot; exit, ie. if an IO<br>&gt; action in the loop encounters a particular value I want it to abort the<br>&gt; loop.<br>&gt;<br>&gt; Now so far, pls don&#39;t shoot, I have done this by throwing IO Exceptions and<br>
&gt; catching them. I&#39;m trying to rewrite this using Continuatios / callCC but<br>&gt; can&#39;t figure out where to place what.<br>&gt;<br>&gt; I certainly don&#39;t have the intuition yet and funny enough not even in RWH I<br>
&gt; could find some Cont/ContT examples.<br>&gt;<br>&gt; Would someone please draw me an example?<br>&gt;<br>&gt; GŁnther<br>&gt;<br>&gt; _______________________________________________<br>&gt; Haskell-Cafe mailing list<br>
&gt; <a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>&gt; <a href="http://www.haskell.org/mailman/listinfo/haskell-cafe">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>&gt;<br><br><br>
<br>-- <br>Push the envelope. †Watch it bend.<br><br>