Reputation: 23729
Problem: having a typeclass MapLike, looking like a map type, implement an instance for MapLike for the type ListMap. ListMap is defined as a list of pairs (key, value). For each key there must be only 1 value. insert function changes the old value to the new one if the key is contained in the map.
It implemented it partially, but for insert function I get an error:
error:
• Couldn't match expected type ‘[ListMap k0 v0]’ with actual type ‘ListMap k v’ • In the second argument of ‘(:)’, namely ‘t’ In the expression: (ListMap (k, v) : t) In the expression: let t = insert key val (ListMap xs) in (ListMap (k, v) : t)
I don't understant what's wrong, I am checking whether the key is in the head of the list. If it's there, we change the value and cons it with the tail. If it's not there, we get the list with exchanged or concatenated key/value pair and add a head to it. What's wrong?
import Prelude hiding (lookup)
import qualified Data.List as L
class MapLike m where
empty :: m k v
lookup :: Ord k => k -> m k v -> Maybe v
insert :: Ord k => k -> v -> m k v -> m k v
delete :: Ord k => k -> m k v -> m k v
fromList :: Ord k => [(k,v)] -> m k v
fromList [] = empty
fromList ((k,v):xs) = insert k v (fromList xs)
newtype ListMap k v = ListMap { getListMap :: [(k,v)] }
deriving (Eq,Show)
instance MapLike ListMap where
empty = ListMap []
lookup key (ListMap []) = Nothing
lookup key (ListMap ((k, v):xs)) | key == k = Just v
| otherwise = lookup key (ListMap xs)
insert key val (ListMap []) = ListMap [(key, val)]
insert key val (ListMap ((k, v):xs)) | key == k = ListMap ((k, val):xs)
| otherwise = let (ListMap t) = insert key val (ListMap xs) in
(ListMap (k, v):t) -- <-?
Upvotes: 0
Views: 47
Reputation: 144136
ListMap (k, v):t
is parsed as ((ListMap (k, v)) : t)
. Since (:)
has type a -> [a] -> [a]
, and ListMap
constructs a ListMap k v
, t
must have type [ListMap k v]
to typecheck. Since t
(correctly) has type [(k, v)]
the check fails. You also have another error, namely that (k, v)
does not have the required type of [(k, v)]
to be used as an argument to the ListMap
constructor.
You can fix both of these by ensuring the parse you want, either:
ListMap ((k, v):t)
or
ListMap $ (k,v):t
Upvotes: 6