haskellcoqchurch-encoding

Church encoding for dependent types: from Coq to Haskell


In Coq I can define a Church encoding for lists of length n:

Definition listn (A : Type) : nat -> Type :=
fun m => forall (X : nat -> Type), X 0 -> (forall m, A -> X m -> X (S m)) -> X m.

Definition niln (A : Type) : listn A 0 :=
fun X n c => n.

Definition consn (A : Type) (m : nat) (a : A) (l : listn A m) : listn A (S m) :=
fun X n c => c m a (l X n c).

Is the type system of Haskell (including its extensions) strong enough to accommodate such definitions? If yes, how?


Solution

  • Sure it is:

    {-# LANGUAGE RankNTypes #-}
    {-# LANGUAGE KindSignatures #-}
    {-# LANGUAGE DataKinds #-}
    {-# LANGUAGE GADTs #-}
    
    import Data.Kind        -- Needed for `Type`
    
    data Nat = Z | S Nat    -- Roll your own...
    
    type List (a :: Type) (n :: Nat) =
      forall (x :: Nat -> Type). x Z -> (forall (m :: Nat). a -> x m -> x (S m)) -> x n
    
    niln :: List a Z
    niln = \z _ -> z
    
    consn :: a -> List a n -> List a (S n)
    consn a l = \n c -> c a (l n c)
    

    Further proof (for skeptics) of the isomorphism with the usual GADT formulation:

    data List' (a :: Type) (n :: Nat) where
      Nil :: List' a Z
      Cons :: a -> List' a m -> List' a (S m)
    
    to :: List' a n -> List a n
    to Nil = niln
    to (Cons a l) = consn a (to l)
    
    from :: List a n -> List' a n
    from l = l Nil Cons