<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Use `throwError`, not `fail`. :)<div class=""><br class=""></div><div class="">Forget `fail`. Luckily we are taking it out of `Monad`.<div class=""><br class=""></div><div class="">- Oleg<br class=""><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 01 Dec 2015, at 20:44, Jeffrey Brown <<a href="mailto:jeffbrown.the@gmail.com" class="">jeffbrown.the@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class=""><div class="">I spoke too soon; I'm seeing the same problem with MonadError.<br class=""></div><div class=""><br class=""></div><div class=""><font face="monospace, monospace" class=""> Prelude> :set -XFlexibleContexts</font></div><div class=""><font face="monospace, monospace" class=""> Prelude> import Control.Monad.Except</font></div><div class=""><font face="monospace, monospace" class=""> Prelude Control.Monad.Except> let f = (fail "be Left!" :: (MonadError String m) => m ())</font></div><div class=""><font face="monospace, monospace" class=""> Loading package transformers-0.4.2.0 ... linking ... done.</font></div><div class=""><font face="monospace, monospace" class=""> Loading package mtl-2.2.1 ... linking ... done.</font></div><div class=""><font face="monospace, monospace" class=""> Prelude Control.Monad.Except> f :: Either String ()</font></div><div class=""><font face="monospace, monospace" class=""> *** Exception: be Left!</font></div><div class=""><font face="monospace, monospace" class=""> Prelude Control.Monad.Except></font> </div></div><div class=""><br class=""></div><div class=""><br class=""></div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Mon, Nov 30, 2015 at 6:18 PM, Jeffrey Brown <span dir="ltr" class=""><<a href="mailto:jeffbrown.the@gmail.com" target="_blank" class="">jeffbrown.the@gmail.com</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="">Oleg's suggestion works! I just had to add these two lines in order to use it:<div class=""><div class=""><br class=""></div><div class=""><font face="monospace, monospace" class=""> {-# LANGUAGE FlexibleContexts #-}</font></div><div class=""><font face="monospace, monospace" class=""> import Control.Monad.Except -- mtl library</font></div></div><div class=""><br class=""></div><div class="">Thanks, everybody!</div></div><div class="gmail_extra"><div class=""><div class="h5"><br class=""><div class="gmail_quote">On Mon, Nov 30, 2015 at 2:38 PM, Oleg Grenrus <span dir="ltr" class=""><<a href="mailto:oleg.grenrus@iki.fi" target="_blank" class="">oleg.grenrus@iki.fi</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><br class=""><div class=""><span class=""><blockquote type="cite" class=""><div class="">On 01 Dec 2015, at 00:34, Oleg Grenrus <<a href="mailto:oleg.grenrus@iki.fi" target="_blank" class="">oleg.grenrus@iki.fi</a>> wrote:</div><br class=""><div class=""><div style="word-wrap:break-word" class="">Hi, Jeffrey<div class=""><br class=""></div><div class="">in short: `fail` of `Either e` throws an exception (i.e. is not overriden, default implementation is `fail s = error s`) [1, 2]</div><div class=""><br class=""></div><div class="">For `Maybe`, fail is defined as `fail _ = Nothing`; which is good default. [3] </div><div class=""><br class=""></div><div class="">You probably want to use for example `throwError from `mtl` package [4]:</div><div class=""><br class=""></div><div class=""><div dir="ltr" class=""><div class=""></div></div></div></div></div></blockquote><div class=""><br class=""></div></span><div class="">I haven’t still tested it, but less wrong context is `MonadError String m`:</div><br class=""><div class=""><div style="word-wrap:break-word" class=""><div class=""><div dir="ltr" class=""><div class=""><font face="monospace, monospace" class=""> gelemM :: (MonadError String m) => MyGraph -> Node -> m ()</font></div><div class=""><div class=""><div class=""><font face="monospace, monospace" class=""> gelemM g n = if gelem n g -- FGL's gelem function returns</font></div><div class=""><font face="monospace, monospace" class=""> then return () -- True if the node is in the graph</font></div><div class=""><font face="monospace, monospace" class=""> else throwError "Node not in Graph" -- False otherwise</font></div></div></div></div></div></div></div><div class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word" class=""><div class=""><br class=""></div><div class="">[1] <a href="https://hackage.haskell.org/package/base-4.8.1.0/docs/src/Data.Either.html#line-137" target="_blank" class="">https://hackage.haskell.org/package/base-4.8.1.0/docs/src/Data.Either.html#line-137</a></div><div class="">[2] <a href="https://hackage.haskell.org/package/base-4.8.1.0/docs/src/GHC.Base.html#Monad" target="_blank" class="">https://hackage.haskell.org/package/base-4.8.1.0/docs/src/GHC.Base.html#Monad</a></div><div class="">[3] <a href="https://hackage.haskell.org/package/base-4.8.1.0/docs/src/GHC.Base.html#line-642" target="_blank" class="">https://hackage.haskell.org/package/base-4.8.1.0/docs/src/GHC.Base.html#line-642</a></div><div class="">[4] <a href="http://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Except.html#v:throwError" target="_blank" class="">http://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Except.html#v:throwError</a></div><div class=""><br class=""></div><div class="">- Oleg</div><div class=""><br class=""><div class=""><div class=""><blockquote type="cite" class=""><div class="">On 01 Dec 2015, at 00:25, Jeffrey Brown <<a href="mailto:jeffbrown.the@gmail.com" target="_blank" class="">jeffbrown.the@gmail.com</a>> wrote:</div><br class=""><div class=""><div dir="ltr" class=""><div class="">I've written a monadic function which in a Maybe context produces a Nothing when it fails (as intended), but in an Either context produces an Exception rather than a Left.</div><div class=""><br class=""></div><div class="">Here's a tiny demonstration. "tinyGraph" below has one Node, 0, with the label "dog". If I try to change the label at Node 0 to "cat", it works. If I try to change the label at Node 1 to "cat", it fails, because Node 1 is not in the graph.</div><div class=""><br class=""></div><div class=""><font face="monospace, monospace" class=""> type MyGraph = Gr String String</font></div><div class=""><font face="monospace, monospace" class=""><br class=""></font></div><div class=""><font face="monospace, monospace" class=""> tinyGraph = mkGraph [(0, "dog")] [] :: MyGraph</font></div><div class=""><font face="monospace, monospace" class=""><br class=""></font></div><div class=""><font face="monospace, monospace" class=""> maybeSucceed = replaceStringAtNodeM tinyGraph 0 "cat" :: Maybe MyGraph</font></div><div class=""><font face="monospace, monospace" class=""> -- == Just (mkGraph [(0,"cat")] [])</font></div><div class=""><font face="monospace, monospace" class=""> maybeFail = replaceStringAtNodeM tinyGraph 1 "cat" :: Maybe MyGraph</font></div><div class=""><font face="monospace, monospace" class=""> -- == Nothing</font></div><div class=""><font face="monospace, monospace" class=""><br class=""></font></div><div class=""><font face="monospace, monospace" class=""> eitherSucceed = replaceStringAtNodeM tinyGraph 0 "cat" :: Either String MyGraph</font></div><div class=""><font face="monospace, monospace" class=""> -- == Right (mkGraph [(0,"cat")] [])</font></div><div class=""><font face="monospace, monospace" class=""> eitherFail = replaceStringAtNodeM tinyGraph 1 "cat" :: Either String MyGraph</font></div><div class=""><font face="monospace, monospace" class=""> -- *** Exception: Node not in Graph</font></div><div class=""><br class=""></div><div class="">Here's the code:</div><div class=""><br class=""></div><div class=""><font face="monospace, monospace" class=""> import Data.Graph.Inductive -- FGL, the Functional Graph Library</font></div><div class=""><font face="monospace, monospace" class=""><br class=""></font></div><div class=""><font face="monospace, monospace" class=""> gelemM :: (Monad m) => MyGraph -> Node -> m ()</font></div><div class=""><font face="monospace, monospace" class=""> gelemM g n = if gelem n g -- FGL's gelem function returns</font></div><div class=""><font face="monospace, monospace" class=""> then return () -- True if the node is in the graph</font></div><div class=""><font face="monospace, monospace" class=""> else fail "Node not in Graph" -- False otherwise</font></div><div class=""><font face="monospace, monospace" class=""><br class=""></font></div><div class=""><font face="monospace, monospace" class=""> replaceStringAtNode :: MyGraph -> Node -> String -> MyGraph</font></div><div class=""><font face="monospace, monospace" class=""> replaceStringAtNode g n e = let (Just (a,b,c,d),g') = match n g</font></div><div class=""><font face="monospace, monospace" class=""> in (a,b,e,d) & g'</font></div><div class=""><font face="monospace, monospace" class=""><br class=""></font></div><div class=""><font face="monospace, monospace" class=""> replaceStringAtNodeM :: (Monad m) => MyGraph -> Node -> String -> m MyGraph</font></div><div class=""><font face="monospace, monospace" class=""> replaceStringAtNodeM g n s = do</font></div><div class=""><font face="monospace, monospace" class=""> gelemM g n</font></div><div class=""><font face="monospace, monospace" class=""> return $ replaceStringAtNode g n s</font></div><div class=""><font face="monospace, monospace" class=""> -- if evaluated, the pattern match in </font><span style="font-family:monospace,monospace" class="">replaceStringAtNode must succeed,</span></div><div class=""><span style="font-family:monospace,monospace" class=""> -- because gelemM catches the case where n is not in the graph</span></div><div class=""><br class=""></div><div class="">[1] <a href="https://github.com/JeffreyBenjaminBrown/digraphs-with-text/blob/master/test/monad_fail_problems.hs" target="_blank" class="">https://github.com/JeffreyBenjaminBrown/digraphs-with-text/blob/master/test/monad_fail_problems.hs</a></div><div class=""><br class=""></div><div class=""><br class=""></div>-- <br class=""><div class=""><div dir="ltr" class="">Jeffrey Benjamin Brown</div></div>
</div>
_______________________________________________<br class="">Haskell-Cafe mailing list<br class=""><a href="mailto:Haskell-Cafe@haskell.org" target="_blank" class="">Haskell-Cafe@haskell.org</a><br class=""><a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" target="_blank" class="">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br class=""></div></blockquote></div><br class=""></div></div></div>_______________________________________________<br class="">Haskell-Cafe mailing list<br class=""><a href="mailto:Haskell-Cafe@haskell.org" target="_blank" class="">Haskell-Cafe@haskell.org</a><br class=""><a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" target="_blank" class="">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br class=""></div></blockquote></div></div></div><br class=""></div></blockquote></div><br class=""><br clear="all" class=""><div class=""><br class=""></div></div></div><span class="HOEnZb"><font color="#888888" class="">-- <br class=""><div class=""><div dir="ltr" class="">Jeffrey Benjamin Brown</div></div>
</font></span></div>
</blockquote></div><br class=""><br clear="all" class=""><div class=""><br class=""></div>-- <br class=""><div class="gmail_signature"><div dir="ltr" class="">Jeffrey Benjamin Brown</div></div>
</div>
</div></blockquote></div><br class=""></div></div></div></body></html>