Reputation: 53715
I have been fiddling with general type classes for lists in Haskell.
class HasEmpty a where
empty :: a
isEmpty :: a -> Bool
class HasEmpty (l a) => List l where
cons :: a -> l a -> l a
uncons :: l a -> (a, l a)
To give you an idea of how it might work, here are instances for []
:
instance HasEmpty [a] where
empty = []
isEmpty [] = True
isEmpty _ = False
instance List [] where
cons = (:)
uncons (x:xs) = (x,xs)
However, this raises an error:
Not in scope: type variable 'a'
This is caused by the constraint HasEmpty (l a)
. I am not desperately interested in this particular example, but I am interested in the concept in general. HasEmpty
is a class for types of kind *
, while List
is a class for types of kind * -> *
. Is it possible for me to make a typeclass constraint of a different kind than the typeclass it is constraining?
Upvotes: 4
Views: 375
Reputation: 7158
In any case you can always express underlying logic either using multiparameter typeclasses (as in fact it is done in ListLike):
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
class HasEmpty a where
empty :: a
isEmpty :: a -> Bool
class HasEmpty (l a) => List l a where
cons :: a -> l a -> l a
uncons :: l a -> (a, l a)
instance HasEmpty [a] where
empty = []
isEmpty [] = True
isEmpty _ = False
instance List [] a where
cons = (:)
uncons (x:xs) = (x,xs)
Or more elegantly via type families:
{-# LANGUAGE TypeFamilies #-}
class HasEmpty a where
empty :: a
isEmpty :: a -> Bool
class HasEmpty a => List a where
type Elem a :: *
cons :: Elem a -> a -> a
uncons :: a -> (Elem a, a)
instance HasEmpty [a] where
empty = []
isEmpty [] = True
isEmpty _ = False
instance List [a] where
type Elem [a] = a
cons = (:)
uncons (x:xs) = (x,xs)
Upvotes: 3
Reputation: 170899
Of course you can. E.g. this will work fine for the same two classes:
class HasEmpty (l ()) => List l where
cons :: a -> l a -> l a
uncons :: l a -> (a, l a)
or (where List1 :: (* -> *) -> * -> *
)
class HasEmpty1 (l a) => List1 l a where
cons :: a -> l a -> l a
uncons :: l a -> (a, l a)
What you can't do is add new variables in constraints.
Upvotes: 2