The following are legal:
class Jabber a where
wocky :: a -> a
instance Jabber Int where
wocky = undefined
instance Jabber [a] where
wocky = undefined
This one isn't:
instance Jabber [Int] where
wocky = undefined
Unless you are using the following:
{-# LANGUAGE FlexibleInstances #-}
A similar extension is
{-# LANGUAGE TypeSynonymInstances #-}
which let's you do something like:
type Ball = [Int]
instance Jabber Ball where
wocky = undefined
This is kind of important because String is just [Char]; you will need it if you want to specialize on String without making some sort of silly proxy type.
{-# LANGUAGE TypeSynonymInstances #-}
instance Jabber String where
wocky = undefined
Okay, remember this guy?
data SEither a b = SLeft a | SRight b
class Jabber a where
wocky :: a b -> a b
instance Jabber (SEither e) where
wocky = undefined
Well, you're going to need FlexibleInstances in order to do something like the following:
instance Jabber (SEither Int) where
wocky = undefined
and also for the more exotic form:
data SMaybe a = SJust a | SNothing
instance Jabber (SEither (SMaybe a)) where
wocky = undefined
Finally, last time I mentioned functional dependencies. There's an alternative to them called Type Families. I'm not going to go into very much detail about them because I haven't fully wrapped my head around them yet. However, if you looked at functional dependencies and thought, "yeah that's the functionality that I want, but I really don't agree with the philosophy", then check out type families. They seem similar to generalized algebraic data types (GADTs) at least philosophically, so if you like GADTs they might be the thing for you.
No comments:
Post a Comment