Stefan O'Rear stefanor at cox.net
Mon Feb 26 18:19:02 EST 2007

On Mon, Feb 26, 2007 at 04:35:06PM +0100, Pepe Iborra wrote:
> I am really curious about this style of programming, and find myself
> playing with it from time to time.
> The example so far is very nice, but the funniest part is missing.
> That is, defining appendL.
>
> > appendL :: List a t1 -> List a t2 -> List a t3
>
> This says that the append of a list of length t1 and a list of length
> t2 is a list of whatever length t3 we want. Obviously this is not
> true and will not typecheck.
> After some healthy days of reading papers and theses, I've found at
> least three ways of defining it.
>
> First, via existentials:
> > appendL1 :: List a t1 -> List a t2 -> exists t3. List a t3
>
> Second, attaching a proof. Question: what would be the advantage of
> the proof here?
> > data Add a b c where Base :: Add NilT a a ; Step :: Add a b c ->
> Add (ConsT a) b (ConsT c)
> > appendL2 :: List a t1 -> List a t2 -> exists t3. (Add t1 t2 t3,
> List a t3)
>
> Third, via Type Classes.
> \begin{code}
> class AddList a b c | a b -> c
>         where append :: List x a -> List x b -> List x c
> instance AddList NilT b b
>         where append Nil x = x
> instance AddList a b c => AddList (ConsT a) b (ConsT c)
>         where append (Cons x l) l' = Cons x (append l l')
> \end{code}
>
>
> Given the three methods, I wouldn't know which one should be
> preferred, and why.
> In the first one you pay the burden of programming with existentials.
> The second one in addition to that is the least efficient, as
> building the proof surely has a cost. Since we are building it, isn't
> there a way to use it to remove the existential?
> Finally, with the third one your compiler will produce error messages
> that will make you swear, apart from possible efficiency losses too.

Personally I like the GADT approach best since it is very flexible and
convienient.  I have never used a purpose-build computer proof system,
but (modulo _|_) it took me less than 10 minutes to answer LoganCapaldo
(on #haskell)'s challenge to proof that + was commutative ( http://hpaste.org/522 ).

Now, efficiency concerns.  GHC haskell already uses higher-than-value-level
proofs to implement newtypes/GADTs/ATs; efficiency concerns are addressed
in a strikingly adhoc way, by promoting equality to the KIND level, allowing
type erasure to remove the overhead of checking.  Chakravarty, Peyton Jones,
we'd really like a general kind-level proof system!