Looking at Learn You a Haskell, I implemented a function that, given a binary tree, i.e. left and right branches, give a list of Directions
and give the element at that location.
Here's the Tree
:
data Tree a = Empty | Node a (Tree a) (Tree a) deriving (Show)
And then the functions:
elemAt :: Directions -> Tree a -> a
elemAt [] (Node x _ _) = x
elemAt (R:ds) (Node _ _ r) = elemAt ds r
elemAt (L:ds) (Node _ l _) = elemAt ds l
But, I re-wrote it to be safe (maybe not)
maybeElemAt :: Directions -> Tree a -> Maybe a
maybeElemAt [] (Node x _ _) = Just x
maybeElemAt (R:ds) (Node _ _ Empty) = Nothing
maybeElemAt (R:ds) (Node _ _ r) = maybeElemAt ds r
maybeElemAt (L:ds) (Node _ Empty _) = Nothing
maybeElemAt (L:ds) (Node _ l _) = maybeElemAt ds l
Testing
anotherTree :: Tree Char
anotherTree = Node 'A' (Node 'B' Empty Empty) Empty
ghci> maybeElemAt [R,R,R] anotherTree
Nothing
ghci> maybeElemAt [R] anotherTree
Nothing
ghci> maybeElemAt [L] anotherTree
Just 'B'
Please critique my implementations of either function.
1 Answer 1
It's not that safe.
*Main> maybeElemAt [] Empty
*** Exception: tree.hs:(7,1)-(11,54): Non-exhaustive patterns in function maybeElemAt
So let's add a pattern
maybeElemAt :: Directions -> Tree a -> Maybe a
maybeElemAt [] (Node x _ _) = Just x
maybeElemAt (R:ds) (Node _ _ Empty) = Nothing
maybeElemAt (R:ds) (Node _ _ r) = maybeElemAt ds r
maybeElemAt (L:ds) (Node _ Empty _) = Nothing
maybeElemAt (L:ds) (Node _ l _) = maybeElemAt ds l
maybeElemAt _ Empty = Nothing
And now we can see that two of the patterns can be removed:
maybeElemAt [] (Node x _ _) = Just x
maybeElemAt (R:ds) (Node _ _ r) = maybeElemAt ds r
maybeElemAt (L:ds) (Node _ l _) = maybeElemAt ds l
maybeElemAt _ Empty = Nothing
GHC has an option -fwarn-incomplete-patterns
, or you can use -W
to get that plus other warnings. See Warnings and sanity-checking in the GHC User's Guide.