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]
base
package 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