Assume I have encoded the natural numbers in Haskell types, and that I have a way of adding and subtracting from them:
data Zero
data Succ n
-- ...
Oh, my... FlexibleContexts??? NoMonomorphismRestriction??? Come on, guys, isn't it exactly what TypeFamilies are for?
{-# LANGUAGE TypeFamilies #-}
data Zero = Zero
newtype Succ n = Succ n
zero = Zero
one = Succ zero
two = Succ one
three = Succ two
class BuildList n where
type BL n
buildListPrefix :: n -> ([String] -> [String]) -> BL n
instance BuildList Zero where
type BL Zero = [String]
buildListPrefix Zero h = h []
instance BuildList n => BuildList (Succ n) where
type BL (Succ n) = String -> BL n
buildListPrefix (Succ n) h s = buildListPrefix n (h . (s:))
buildList:: BuildList n => n -> BL n
buildList n = buildListPrefix n id