Skip to main content

Proof Support for a Haskell-like language

Supervisor

Suitable for

MSc in Advanced Computer Science
Computer Science, Part B
Computer Science, Part C

Abstract

What?

The purpose of this project would be to implement an interactive system to support the discovery (and pretty presentation) of equational proofs by a combination of “automatic choice” and human guidance. Richard Bird, acknowledging Mike Spivey’s unpublished work, sketched an implementation of the simplest form of such a “proof assistant” in Haskell in his most excellent book: Thinking Functionally with Haskell. The project would start by implementing a similar assistant with a convenient interactive workflow for discovering, recording, and checking proofs.

The tool should also support the use of appropriate induction rules derived automatically from data declarations.

An interesting challenge will be the provision of convenient methods for providing human guidance for the application of algebraic laws (such as associativity, commutativity, distributivity) at appropriate points in a proof. Although now somewhat long in the tooth, the Jape generic proof editor still provides (in its functional programming example theory) a working concrete example of the sort of guidance that could be used here, and a user interface by which such guidance can be communicated. Our slogan while building Jape (and many of its example theories) was “Proof by Pointing”. The Jape GitHub repository is here.

Equational Proofs

Many Haskell proofs take the form of straightforward equational rewriting using definitions or derived laws left-to-right as rules. Typically the discovery of a proof of

    lhs = rhs

will take the form

     lhs
    = { rule name
     lhs1
    = { rule name
     lhs2
    .
     lhsn
    = { rule name}
    crux        

followed by

     rhs
    = { rule name
     rhs1
    = { rule name
     rhs2
    ...
     rhsm
    = { rule name
    crux

Where crux is the common term to which both sides can be reduced. This style of presentation relies implicitly on the transitivity of equality.

Aside: it is annoying that some authors obfuscate these sensible discovery steps by a linearised presentation “as if” the post-crux proof had been discovered by using rules ``right to left’’

    ...
    crux
    = { rule name
     rhsm
    = { rule name
    ...
     rhs2
    = { rule name
     rhs1
    = { rule name
     rhs

In our experience such presentations can be pedagogically harmful.

Sometimes the choice of rule at each stage is almost automatic: “pretend you are the Haskell interpreter”. At other times firm human guidance (and/or the invention of lemmas) is needed. For example, a proof of

    (rev * rev) . swap . (rev * rev) . swap
   =
   ...
   =
   id

in the presence of laws/definitions

    rev . rev     = id
    swap(y,z)     = (z,y)
    (f * g)(y, z) = (f x, g y)

can use the lemmas

    swap . (f*g) . swap = g*f
    (f * g) . (h *j) = (f . h) * (g . j)

as well as timely invocation of the associativity of composition.