data Nil a = Nil infixr 6 `Cons` data Cons fs a = Cons a (fs a) data Unary fs a = Z (fs (fs a)) | S (Unary (Cons fs) a) type Square = Unary Nil zero :: Square a zero = Z Nil one :: Square Int one = S . Z $ (1 `Cons` Nil) `Cons` Nil two :: Square Int two = S . S . Z $ (1 `Cons` 2 `Cons` Nil) `Cons` (3 `Cons` 4 `Cons` Nil) `Cons` Nil size' :: Unary fs a -> Int size' (Z _) = 0 size' (S s) = 1 + size' s size :: Square a -> Int size = size'