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