I'm currently trying to implement linked lists in Haskell. So far everything works, including functions for working with these linked lists, but my issue is in the Show
instance. My code:
data LinkedList a = EmptyList | Node a (LinkedList a)
instance (Show a) => Show (LinkedList a) where
show EmptyList = "{ }"
show l = "{ " ++ showLL l ++ " }"
where
showLL (Node x EmptyList) = show x
showLL (Node x l) = show x ++ " -> " ++ showLL l
If I remove the (Show a)
constraint, Haskell freaks out because there's no guarantee that a
is showable. But when I try print EmptyList
, the constraint cannot be solved since EmptyList
doesn't have a type a
which is or isn't showable.
Trying to declare two instances, one with the constraint and one without, gives me the duplicate instance declaration error. Trying to declare it as an instance of LinkedList
instead of (LinkedList a)
also gives me an error since it expects an argument to be passed to LinkedList
(i.e. a
).
Here is the weirdest part: declaring an instance for Functor
prevents the error from showing up:
instance Functor LinkedList where
fmap _ EmptyList = EmptyList
fmap f (Node x l) = Node (f x) (fmap f l)
Note that fmap _ EmptyList = EmptyList
, meaning that regardless of what function I want to map onto an EmptyList
the result will just be an EmptyList
.
The part that is confusing to me:
print $ EmptyList -- error
print $ fmap id EmptyList -- error
print $ fmap (*2) EmptyList -- no error! output is "{ }" as expected
So how can I print both a list that is empty and one that is not? And why on Earth does mapping any function that isn't id
(or anything equivalent like \x -> x
) not give the same error? Does the fmap
function somehow return an EmptyList
that isn't the same as the regular EmptyList
?
Thanks!
(For the record, I'm using GHCi v8.6.5)