type Church = abstract Apply<'T> : ('T -> 'T) * 'T -> 'T let zero = { new Church with member self.Apply(f, x) = x } let succ (nat : Church) = { new Church with member self.Apply(f, x) = f <| nat.Apply(f, x) } let one = succ zero let two = succ one let (<+>) (first : Church) (second : Church) = first.Apply(succ, second) let (<*>) (first : Church) (second : Church) = first.Apply((<+>) second, zero) let (<^>) (first : Church) (second : Church) = second.Apply((<*>) first, one) let toInt (nat : Church) = nat.Apply((+)1, 0) let three = two <+> one let six = three <*> two let eight = two <^> three three |> toInt // 3 six |> toInt // 6 eight |> toInt // 8