[Agda] Getting codata right

Dan Licata drl at cs.cmu.edu
Mon Jun 9 04:19:54 CEST 2008


Hi everyone,

Thanks for the interesting thread!

On Jun08, Anton Setzer wrote:
> Concerning pattern matching I suggest that
> for instance
> 
> f : coNat -> Bool
> f (~ Z) = tt
> f (~ (S n)) = ff
> 
> is an abbreviation for
> 
> f : coNat -> Bool
> f x with x *
> ... | Z' = tt
> ... | (S' n) = ff

This notation is actually a lot like something I implemented in GHC last
summer.  We called it "view patterns"; the idea is that you get to call
a function in the middle of pattern matching and then continue matching
on the result.  What you're writing here specializes the notation to ~,
the "unroll and force evaluation" function for the coalg.

In the above code for 'f', the (with x *) version is in some sense more
honest, because it admits that reaching 'x' is a natural pattern
matching boundary (a polarity shift), and that unrolling-and-forcing the
coalgebra is a different sort of thing.  And the with-version is precise
about where and how many times the forcing happens.

The ~ version is less explicit, and, in terms of the operational
behavior, it can actually be a little subtle to get ~ to do the right
thing, or even to decide what the right thing should be.  For example:

=== Is the coNat forced by f? ===

f : coNat -> Bool
f _ = tt

I.e., do you insert the 'with' if there are no ~ patterns?  I'd hope
not, since you sometimes want to write a function that doesn't force its
argument.

=== How many times is the coNat forced by ... ===

f : (Bool * coNat) -> Integer
f (True , ~ Zero)  = 0
f (False , _ ) = 1
f (True , ~ (Succ Zero))  = 2 

... calling f (False , whatever) ?  
    My GHC impl runs it 0 times.  

... calling f (True , Succ Zero) ?  
    My GHC impl runs it 2 times (the two calls to the view don't get
    coalesced because there is another kind of pattern--in this case a
    wildcard--in between them). But one could hope it would only get run
    once in this case.

I.e., how do you decide which ~ patterns on the same argument to group
into a subsidiary case-analysis of a 'with', like you've done in the
example above?  

Since all you want is ~, and there's no way to pattern-match a colagebra
other than ~, it might be reasonable to insist that a given column is
either all ~'s or no ~'s (precluding examples like this one), in which
case it's clear what to do.

Of course, in a pure language like Agda, these difference won't affect
the behavior of a program.  But they will affect (a) run-time
performance and (b) coverage checking, so a programmer needs to know
exactly how the ~'s get desugared.  

-Dan


More information about the Agda mailing list