1

So I have this class:

class Collection c where
    empty :: c key value
    singleton :: key -> value -> c key value
    insert :: Ord key => key -> value -> c key value -> c key value
    looKup :: Ord key => key -> c key value -> Maybe value
    delete :: Ord key => key -> c key value -> c key value
    keys :: c key value -> [key]
    keys x = map fst $ toList x
    values :: c key value -> [value]
    values c = map snd $ toList c
    toList :: c key value -> [(key, value)]
    fromList :: Ord key => [(key,value)] -> c key value
    fromList [] = empty
    fromList ((k, v):xs) = insert k v (fromList xs)

Why is this

instance Collection (PairList k v) where

a bad instantion of the class and this:

instance Collection PairList where

is a good one ? I know that when making maybe an instance of Eq, this is how haskell does it:

instance Eq (Maybe m) where  
    Just x == Just y = x == y  
    Nothing == Nothing = True  
    _ == _ = False  

So instantiations accept parameters... So why is the first one like so ?

2
  • 4
    Do you understand why instance Functor Maybe is correct rather than instance Functor (Maybe a)? Commented Jan 17, 2022 at 19:13
  • 1
    If you're unfamiliar with "kinds", there's a good introductory write-up in LYAH. (Note that the kind * is I believe deprecated in some sense and we're supposed to call it Type now. But you'll definitely see people refer to * often enough, including in @chepner's answer, so it's useful to know that that means the same thing.) Commented Jan 17, 2022 at 20:15

2 Answers 2

6

Based on how c is used, Collection requires something of kind * -> * -> *.

> :k Collection
Collection :: (* -> * -> *) -> Constraint

PairList k v, though, has kind *.

Eq, on the other hand, expects something of kind *, which is exactly what Maybe m is.

> :k Eq
Eq :: * -> Constraint

(Maybe itself has kind * -> *, but applying it to a type variable produces something of kind *.)

Sign up to request clarification or add additional context in comments.

Comments

5

The thing you put in the instance head will be substituted for the class variable everywhere. So, if we combine

class Collection c where
    empty :: c key value
    -- and other stuff, too, of course

and

instance Collection (PairList k v)

we get the type

    empty :: (PairList k v) key value

which doesn't make a lot of sense. But if we combine the class declaration with

instance Collection PairList

then we get the type

    empty :: PairList key value

which makes sense just fine.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.