there are expressive programming languages. And then there are beautiful ones. Haskell, a pure functional programming language, is such a language with its mathematical eloquence.

Transitioning from imperative languages to Haskell can entail more than a brain cramp – the purity of the language lacks the common control structures that give imperative languages their familiar linear organization: the learning curve is steep. Instead, the syntax is equational, the mathematical roots of the language being very apparent. It’s a difficult journey across the landscape of lazy evaluation, static typing, functors, monoids and monads, but worth it just for the insightful possibilities and the exercise of seeing in terms of equations versus sequential operations.

The functional pattern matching is reminiscent of object oriented message dispatching which, with the power of its type declaratives, can create solutions that read very much like a domain specific language. It takes awhile to grok the power of static typing, type classes and instances, which lie at the heart of the language and facilitate such eloquent solutions.

Haskell is way beyond my ken – though, I have been fine tuning my Xmonad desktop environment which is written in Haskell as a means of immersing myself in its delightful power. It is used in academia for esoteric problem domains. I love the Ruby programming language. But there is a hypnotically alluring quality to Haskell’s mathematical form, which sings the language of the universe.

class | subclass of | prelude instances |
---|---|---|

Show | All Prelude types | |

Read | All except IO, (->) | |

Bounded | Int, Char, Bool, (), Ordering, tuples | |

Eq | All except IO, (->) | |

Enum | (), Bool, Char, Ordering, Int, Integer, Float, Double | |

Ord | Eq | All except (->), IO, IOError |

Ix | Ord | Int, Integer, Char, Bool, Enum, tuples |

Num | Eq | Int, Integer, Float, Double |

Real | Ord, Num | Int, Integer, Float, Double |

Fractional | Num | Float, Double |

Integral | Enum, Real | Int, Integer |

RealFrac | Real | Float, Double |

Floating | Fractional | Float, Double |

RealFloat | RealFrac, Floating | Float, Double |

Functor | IO, [], Maybe | |

Monad | IO, [], Maybe | |

MonadPlus | Monad | IO, [], Maybe |

Note: Haskell type classes are not to be confused with object oriented class specifications

`class Functor f where`

` fmap :: (a -> b) -> f a -> f b`

`instance Functor [] where`

` fmap = map`

` `

`instance Functor Maybe where`

` fmap f (Just x) = Just (f x)`

` fmap f Nothing = Nothing`

` `

`instance Functor (Either a) where`

` fmap f (Right x) = Right (f x)`

` fmap f (Left x) = Left x `

`fmap id = id`

`fmap (f . g) = fmap f . fmap g`

`class (Functor f) => Applicative f where`

` pure :: a -> f a`

` (<*>) :: f (a -> b) -> f a -> f b`

` `

` (<$>) :: (a -> b) -> f a -> f b`

` f <$> x = fmap f x `

`instance Applicative Maybe where`

` pure = Just`

` Nothing <*> _ = Nothing`

` (Just f) <*> something = fmap f something`

` `

`instance Applicative [] where`

` pure x = [x]`

` fs <*> xs = [f x | f <- fs, x <- xs]`

` `

`instance Applicative IO where`

` pure = return`

` a <*> b = do`

` f <- a`

` x <- b`

` return (f x)`

` `

`instance Applicative ((->) r) where`

` pure x = (_ -> x)`

` f <*> g = \x -> f x (g x)`

`pure id <*> v = v`

`pure (.) <*> u <*> v <*> w = u <*> (v <*> w)`

`pure f <*> pure x = pure (f x)`

`u <*> pure y = pure ($ y) <*> u`

`class Monoid m where`

` mempty :: m`

` mappend :: m -> m -> m`

` `

` mconcat :: [m] -> m`

` mconcat = foldr mappend mempty`

`instance Monoid [a] where`

` mempty = []`

` mappend = (++) `

` `

`newtype Any = Any { getAny :: Bool }`

` deriving (Eq, Ord, Read, Show, Bounded)`

` `

`instance Monoid Any where`

` mempty = Any False`

` Any x `mappend` Any y = Any (x || y)`

` `

`newtype All = All { getAll :: Bool }`

` deriving (Eq, Ord, Read, Show, Bounded)`

` `

`instance Monoid All where`

` mempty = All True`

` All x `mappend` All y = All (x && y)`

` `

`instance Monoid Ordering where`

` mempty = EQ`

` LT `mappend` _ = LT`

` EQ `mappend` y = y`

` GT `mappend` _ = GT`

` `

`instance Monoid a => Monoid (Maybe a) where`

` mempty = Nothing`

` Nothing `mappend` m = m`

` m `mappend` Nothing = m`

` Just m1 `mappend` Just m2 = Just (m1 `mappend` m2)`

`mempty `mappend` x = x`

`x `mappend` mempty = x`

`(x `mappend` y) `mappend` z = x `mappend` (y `mappend` z)`

`class (Applicative m) => Monad m where`

` return :: a -> m a`

` (»=) :: m a -> (a -> m b) -> m b`

` `

` (») :: m a -> m b -> m b`

` x » y = x »= _ -> y`

` `

` fail :: String -> m a`

` fail msg = error msg`

Note: the class constraint *Applicative m* is not part of the formal
definition of the monad class – it is inferred. *return* is equivalent
to *pure* of applicative functors.

`instance Monad Maybe where`

` return x = Just x`

` Nothing »= f = Nothing`

` Just x »= f = f x`

` fail _ = Nothing`

` `

`instance Monad [] where`

` return x = [x]`

` xs »= f = concat (map f xs)`

` fail _ = []`

`Left Identity: return x >>= f = f x`

`Right Identity: m >>= return = m`

`Associativity: (m >>= f) >>= g = m >>= (\x -> f x >>= g)`

`foo :: IO ()`

`foo = ... >>= (\x ->`

` … »`

` … »= (\y ->`

` ... (.. x .. y)))`

can be expressed with Haskell’s syntactic sugar as..

`foo :: IO ()`

`foo = do`

` x <- …`

` …`

` y <- …`

` ... (.. x .. y)`

which is just different syntax for chaining monadic values. In effect, monads sequence operations to simulate stateful or imperative computations.