module ThunkNat exposing (..) type Nat = Z | S (Thunk Nat) type alias Thunk a = () -> a force : Thunk a -> a force thunk = thunk () fromInt : Int -> Nat fromInt i = if i <= 0 then Z else S (\_ -> fromInt (i-1)) toInt : Nat -> Int toInt = let foo acc n = case n of Z -> acc S n_ -> foo (1 + acc) (force n_) in foo 0 toString : Nat -> String toString = let foo acc n = case n of Z -> acc S n_ -> foo ("S" ++ acc) (force n_) in foo "Z" equals : Nat -> Nat -> Bool equals x y = case (x, y) of (Z, Z) -> True (S x_, S y_) -> equals (force x_) (force y_) (_, _) -> False plus : Nat -> Nat -> Nat plus x y = case y of Z -> x S y_ -> S (\_ -> plus x (force y_))