<div dir="ltr"><div>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><br></div><div>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><br></div><div><font face="monospace, monospace"> type MyGraph = Gr String String</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"> tinyGraph = mkGraph [(0, "dog")] [] :: MyGraph</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"> maybeSucceed = replaceStringAtNodeM tinyGraph 0 "cat" :: Maybe MyGraph</font></div><div><font face="monospace, monospace"> -- == Just (mkGraph [(0,"cat")] [])</font></div><div><font face="monospace, monospace"> maybeFail = replaceStringAtNodeM tinyGraph 1 "cat" :: Maybe MyGraph</font></div><div><font face="monospace, monospace"> -- == Nothing</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"> eitherSucceed = replaceStringAtNodeM tinyGraph 0 "cat" :: Either String MyGraph</font></div><div><font face="monospace, monospace"> -- == Right (mkGraph [(0,"cat")] [])</font></div><div><font face="monospace, monospace"> eitherFail = replaceStringAtNodeM tinyGraph 1 "cat" :: Either String MyGraph</font></div><div><font face="monospace, monospace"> -- *** Exception: Node not in Graph</font></div><div><br></div><div>Here's the code:</div><div><br></div><div><font face="monospace, monospace"> import Data.Graph.Inductive -- FGL, the Functional Graph Library</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"> gelemM :: (Monad m) => MyGraph -> Node -> m ()</font></div><div><font face="monospace, monospace"> gelemM g n = if gelem n g -- FGL's gelem function returns</font></div><div><font face="monospace, monospace"> then return () -- True if the node is in the graph</font></div><div><font face="monospace, monospace"> else fail "Node not in Graph" -- False otherwise</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"> replaceStringAtNode :: MyGraph -> Node -> String -> MyGraph</font></div><div><font face="monospace, monospace"> replaceStringAtNode g n e = let (Just (a,b,c,d),g') = match n g</font></div><div><font face="monospace, monospace"> in (a,b,e,d) & g'</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"> replaceStringAtNodeM :: (Monad m) => MyGraph -> Node -> String -> m MyGraph</font></div><div><font face="monospace, monospace"> replaceStringAtNodeM g n s = do</font></div><div><font face="monospace, monospace"> gelemM g n</font></div><div><font face="monospace, monospace"> return $ replaceStringAtNode g n s</font></div><div><font face="monospace, monospace"> -- if evaluated, the pattern match in </font><span style="font-family:monospace,monospace">replaceStringAtNode must succeed,</span></div><div><span style="font-family:monospace,monospace"> -- because gelemM catches the case where n is not in the graph</span></div><div><br></div><div>[1] <a href="https://github.com/JeffreyBenjaminBrown/digraphs-with-text/blob/master/test/monad_fail_problems.hs">https://github.com/JeffreyBenjaminBrown/digraphs-with-text/blob/master/test/monad_fail_problems.hs</a></div><div><br></div><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr">Jeffrey Benjamin Brown</div></div>
</div>