The definition
class Foo a where
bar :: a -> a -> Bool
is very simililar to
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
and here is when you can find how useful can it be:
Imagine you've got slugs, and want to know if they can procreate, and there is a rare species with hermaphrodite type, you can use your typeclass:
data Slug = M | F | H
class Foo a where
bar :: a -> a -> Bool
instance Foo Slug where
bar H _ = True
bar _ H = True
bar F M = True
bar M F = True
bar _ _ = False
Or, with temperatures:
You want to know if mixing water will get you warm water:
data Temp = Cold | Hot | Warm
instance Foo Temp where
bar Warm _ = True
bar _ Warm = True
bar Hot Cold = True
bar Cold Hot = True
bar _ _ = False
So, that typeclass now could be named sort of "Mixable", and the method, "mix", and it would be less confusing to read for type Slug and Temperature.
Now, if you want to watch it in action with some example, I can came up now with something like...
mix :: Foo a => [a] -> [a] -> [Bool]
mix xs ys = zipWith bar xs ys
$> mix [M,M,H,F] [F,F,F,F]
=> [True,True,True,False]
but there is a restriction with mix, you can just mix Mixable things. so if you do:
mix [1,1] [2,2]
will break:
9:1: error:
• No instance for (Foo Bool) arising from a use of ‘mix’
• In the expression: mix [True, True] [False, True]
In an equation for ‘it’: it = mix [True, True] [False,
And that means, that you can organize you data types to satisfy the mix function according its structure, or your needs.
Level 2:
What if you want a default implementation for Slug and Temp? Because you saw they where similar, so you could do:
class (Bounded a, Eq a) => Mixable a where
mix :: a -> a -> Bool
mix e1 e2 = e1 /= e2 || any (\x -> x /= minBound && x /= maxBound) [e1, e2]
data Slug = F | H | M deriving (Bounded, Eq, Show)
data Temp = Cold | Warm | Hot deriving (Bounded, Eq, Show)
instance Mixable Slug
instance Mixable Temp
mixAll :: Mixable a => [a] -> [a] -> [Bool]
mixAll xs ys = zipWith mix xs ys
main = do
putStrLn $ show (mixAll [F,F,F,M,M,M,H] [F,M,H,M,F,H,H])
putStrLn $ show (mixAll [Cold,Cold,Cold,Hot,Hot,Hot,Warm] [Cold,Hot,Warm,Hot,Cold,Warm,Warm])
[False,True,True,False,True,True,True]
[False,True,True,False,True,True,True]
basepackage alone, and probably thousands more on Hackage. Ord, Eq, and Show are just a tiny tip of an ice cube chipped off the top of the iceberg. - Daniel Wagner