How to catch and ignore an Error call in Haskell

Viewed 130

I'm trying to understand how to handle calls error in Haskell. For example: I have this graph

import Data.Map (Map,empty,member,insert,keys,(!))
import Graphviz

-- | A directed graph
data Graph v = Graph
    { arcsMap :: Map v [v]     -- A map associating a vertex with its successors
    , labelMap :: Map v String -- The Graphviz label of each node
    , styleMap :: Map v String -- The Graphviz style of each node
    }deriving (Show,Eq, Ord)

And I have the function

-- | Returns the successors of a vertex in a graph in ascending order
--
-- We say that `v` is a successor of `u` in a graph `G` if the arc `(u,v)`
-- belongs to `G`.
--
-- Note: Returns the empty list if the vertex does not belong to the graph.
--
-- >>> successors 1 emptyGraph
-- []
-- >>> successors 1 $ addArc (1,2) emptyGraph
-- [2]
-- >>> successors 1 $ addArcs emptyGraph [(1,2),(2,3),(1,3)]
-- [2,3]
successors :: Ord v => v -> Graph v -> [v]
successors v (Graph arcs labels styles) = arcs ! v

The documentation of the operator (!) says : "O(log n). Find the value at a key. Calls error when the element cannot be found."

I want to return an empty list [] when the element can't be found

How should I handle this ? Thank you very much.

1 Answers

You can make use of the !? operator (Ord k => Map k a -> k -> Maybe a) here. This will return a Nothing in case the key does not exist, and Just v with v the value in case that exists, as specified by the documentation:

O(log n). Find the value at a key. Returns Nothing when the element can not be found.

Then we still need to convert that to an empty list. We can use fromMaybe :: a -> Maybe a -> a for that, here we first give a "default" value to use in case of a Nothing, and then we pass it a Maybe a. In case it is a Nothing, we use the default, in case it is a Just v, it will return v:

import Data.Map (Map,empty,member,insert,keys,(!?))
import Data.Maybe(fromMaybe)

successors :: Ord v => v -> Graph v -> [v]
successors v (Graph arcs _ _) = fromMaybe [] (arcs !? v)

or as @Bergi says, we can use findWithDefault :: Ord k => a -> k -> Map k a -> a:

import Data.Map (Map,empty,member,insert,keys,findWithDefault)
import Data.Maybe(fromMaybe)

successors :: Ord v => v -> Graph v -> [v]
successors v (Graph arcs _ _) = findWithDefault [] v arcs
Related