a bestiary of

haskell.

MONSTER

being a true and faithful account of the magnificent beasts that dwell within the lambda calculus — observed, sketched, and humbly recorded by the naturalists of pure abstraction.

Folio I · MMXXVI · Liber Monstrorum Functionalium

❧ Folio II ❧

The Bestiary Index

Six creatures dwell within the codex. Each is a concept made flesh, a pattern with appetite. Approach them with curiosity, not fear — they are tame to those who learn their names.

Order: Categorical

The Monad

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

A serpent that swallows its own tail, then offers it back transformed. Each consumption begets the next; the chain is endless and elegant.

Habitat: IO, Maybe, State, the dark forests of side-effect

Order: Mappable

The Functor

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

A shape-shifter whose outer form remains constant while its inner contents transmute at will. To touch its core, one must first earn its trust.

Habitat: Lists, Trees, every container that breathes

Order: Multi-Limbed

The Applicative

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

A hydra whose many heads act as one, each striking in concert. Sever a limb and another arrives, equally pure, equally lawful.

Habitat: Parsers, Validation, anywhere effects must align

Order: Combinatorial

The Monoid

mappend :: a -> a -> a mempty :: a

An elemental force that gathers all things into itself. Two grains become one mound; one mound and a mountain remain a mountain still.

Habitat: Strings, Sums, the slow accretion of the world

Order: Genealogical

The Typeclass

class Eq a where (==) :: a -> a -> Bool

A great branching family tree, its roots tangled with abstract law, its leaves the concrete instances that bear its name and inherit its rites.

Habitat: Show, Eq, Ord, the polite societies of types

Order: Dormant

The Lazy Thunk

undefined :: a take 5 [1..]

A sleeping dragon coiled around an unevaluated promise. It stirs only when something dares to demand its hoarded answer — and not a moment sooner.

Habitat: Infinite lists, recursive structure, the patient void

❧ Folio III — The Monad ❧

Of the Serpent that Swallows Itself

Much is whispered of the Monad, and most of it is wrong. The naturalist who first encounters this creature is told that it is a burrito, or a box, or a programmable semicolon — each comparison less faithful than the last. The truth is plainer and stranger: the Monad is a serpent that ties together what would otherwise unravel.

It binds. That is its single, tireless act. Given a value cradled in some context, and a function that knows how to extend that context, the Monad weaves them into a single uninterrupted thread. From this small motion the whole fabric of effectful computation is woven — input, output, failure, choice, time itself.

Field observation, recorded in the margins:
greet :: IO ()
greet = do
  putStr "What is your name? "
  name <- getLine
  putStrLn ("Hello, " ++ name ++ ".")

Each <- is a bite. The serpent consumes the result of the prior action and extends the chain by one more link. To the untrained eye it appears as an imperative sequence; to the naturalist it is a single composition, pure and whole, merely described in the order of its unfolding.

The three laws by which the creature lives:
-- Left identity
return a >>= f      ≡  f a
-- Right identity
m >>= return        ≡  m
-- Associativity
(m >>= f) >>= g     ≡  m >>= (\x -> f x >>= g)

Honour these three laws and the Monad is your steadfast companion. Violate them and it will eat its tail forever, returning nothing but the bitter taste of its own ill-formed shape.

❧ Folio IV — The Functor ❧

Of the Shape-Shifter that Keeps its Skin

The Functor is the kindest beast in the codex. It asks only one favour: do not change my outer form. Within that single rule, it permits the naturalist any liberty — reach inside, transform what you find, and return a creature with the same silhouette but a wholly new soul.

The signature it offers is a small contract: fmap :: (a -> b) -> f a -> f b. The container f never changes its kind. A list remains a list; a tree remains a tree; a Maybe remains a Maybe. The contents alone are the field of play.

An instance, recorded in the field:
instance Functor Maybe where
  fmap f Nothing  = Nothing
  fmap f (Just x) = Just (f x)

Two laws bind the Functor as surely as gravity binds a stone: identity (fmap id ≡ id) and composition (fmap (g . f) ≡ fmap g . fmap f). Together they ensure the shape-shifter never loses its way home, no matter how many transformations it endures.

❧ Folio V — Lazy Evaluation ❧

Of the Dragon who Sleeps until Demanded

The Dragon of Lazy Evaluation does not wake for idle curiosity. It sleeps upon its hoard of unevaluated expressions — thunks, by the proper name — and stirs only when something dares to demand their value. To call it is to enter a contract: ask, and you shall receive; ask not, and the dragon dreams on.

This is no slothful trait but a marvellous economy. Whole infinities may be inscribed in the codex without ever filling its pages, because no page is read until needed. Behold the catalogue of natural numbers, complete and infinite, fitting in a single line:

The infinite list, summoned only in part:
naturals :: [Integer]
naturals = [1..]

primes :: [Integer]
primes = sieve [2..]
  where sieve (p:xs) = p : sieve [x | x <- xs, x `mod` p /= 0]

take 10 primes
-- ⇒ [2,3,5,7,11,13,17,19,23,29]

The dragon stirred only ten times. The remaining infinity continues to sleep, untouched, untaxed, untethered to any clock. Such is the gift of laziness: every expression is a promise, and only the kept promises cost anything at all.

A naturalist's caution: the dragon hoards thunks even when you do not need them. In long-running computations, an unspent promise can grow into a heavy tail. The wise tame their beast with strictness annotations — seq, !, deepseq — rousing the dragon at chosen moments, lest the hoard topple.

❧ Folio VI · The Colophon ❧

Thus ends our brief survey of the bestiary. The creatures recorded herein are neither caged nor tamed; they roam the type system as they have always roamed, indifferent to the naturalists who chronicle them. Yet to know their names is to walk among them with a small but necessary courage.

The monster's footprint, left for those who follow:
main :: IO ()
main = do
  putStrLn "Here be Monads."
  let beasts = ["Monad", "Functor", "Applicative",
                "Monoid", "Typeclass", "Lazy Thunk"]
  mapM_ (putStrLn . ("· " ++)) beasts
  putStrLn "— Liber Monstrorum Functionalium —"

Explicit Liber Monstrorum Functionalium.
— copied by an unknown hand, MMXXVI —