
On Fri, Feb 26, 2010 at 04:23:52PM +0300, Miguel Mitrofanov wrote:
I'd say we don't really need subclasses. I mean, what's the difference:
class Eq a where (==) :: a -> a -> Bool instance Eq a => Eq (Maybe a) where Nothing == Nothing = True Just x == Just y = x == y _ == _ = False sort :: Eq a => [a] -> [a]
or
data Eq a = Eq {eq :: a -> a -> Bool} eqMaybe :: Eq a -> Eq (Maybe a) eqMaybe e = Eq {eq = eqM} where eqM Nothing Nothing = True eqM (Just x) (Just y) = eq e x y eqM _ _ = False sort :: Eq a -> [a] -> [a]
Replacing classes with types, we only lose one thing: the compiler won't deduce the right instances for us. I'll trade it for the ability to abstract over them. After all, we CAN deduce the right instances by hand, it's just a finite amount of work (not very big, in my experience).
But then we would lose the invarient that there is a unique pairing between a type and a given class. for instance, you would no longer be able to implement things like Set and Map, For instance if you called the two following functions with different ord arguments, you would suddenly break all the invarients of what 'Set' means. insert :: Ord a -> a -> Set a -> Set a member :: Ord a -> a -> Set a -> Bool The unique correspondence between types and classes (i.e. no local instances) is a main _feature_ of type classes. Often when people think they need local instances, they are just applying type classes when they should be using a different idiom, such as the one you mention. John -- John Meacham - ⑆repetae.net⑆john⑈ - http://notanumber.net/