[Agda] Problem with inductively defined type having (simulated) partial constructors

Wouter Swierstra wss at Cs.Nott.AC.UK
Fri Apr 18 01:14:08 CEST 2008


>  proof1 : {a : Octet} -> {b : Octet} ->
>           (_ : even a IsTrue) -> (_ : even b IsTrue) ->
>           even (a or b) IsTrue
>  proof1 {allzeros} {allzeros} p q = ???
>  proof1 {_ orone} {_} p q = ???
>  proof1 {_} {_ orone} p q = ???
>  proof1 {_ shifted} {_shifted} p q = ???
>
> I can't figure an expression to put in each of these clauses that
> produces Top or Bottom : Set instead of : Set1

So in the first set of question marks, you have to give a proof that  
"even (allzeros or allzeros) IsTrue". By definition of _or_ this is  
the same as a proof of "even allZeros IsTrue". Now by definition of  
even, this is the same as a proof of "True IsTrue" - which is easy:

>  proof1 {allzeros} {allzeros} p q = record {}


In some cases, you will need to use your proof arguments to rule out  
impossible branches. For example, what should the right-hand side be  
in this branch:

>  proof1 {_orone a {p}} {b} q1 q2 = ?

We seem stuck: we need to show that "(a orone) or allzeros" is even,  
which it isn't. Fortunately, this branch is impossible: there's no way  
to provide the q1 argument that proves "a orone" is even. In Agda you  
can write:

>  proof1 {_orone a {p}} {b} () q2

where the "()" means "no argument can ever have this type, so I'm not  
going to bother writing the right-hand side". There's a symmetric case  
if the second argument is "b orone". The other cases are all pretty  
easy. I hope you get the idea.

> I was doing it this way to experiment with things.

Sure - that's the best way to learn. It just appears that you've dug  
yourself into a bit of a hole - please don't think that Agda is all  
hard work and no play!

The way I suggested allows you to write down the type of an n-bit  
word. Nil is a word without bits; you can make a word of size (n + 1)  
from a bit and a word of size n.

> Although constructing an Octet from "allzeros", "shift" and "set bit  
> 0"
> is also nice in a way.

Here's a different way to set things up, that is a bit closer to what  
you're trying to do:

data Word' : Nat -> Bool -> Set where
   Zero : Word' 0 False
   Shift : {n : Nat} -> {b : Bool} -> Word' n b -> Word' (Succ k) False
   OrOne : {n : Nat} -> Word' n False -> Word' n True

Now the type "Word' n b" represents a binary word of with (n + 1) bits  
with the rightmost bit set to b. It's slightly different from your  
data type. Instead of having "allzeros" produce an all-zero vector and  
have shift check that you don't go out of bounds, this representation  
starts with an empty bitvector and uses shift to make longer vectors.

If you use this definition of Word', you should be able to define this  
function, without having to do any proofs:

or : forall {n b1 b2} -> Word' n b1 -> Word' n b2 -> Word' n (bor b1 b2)

where bor is the Boolean or function.

Sorry if this doesn't make any sense, it's getting quite late. Best of  
luck,

   Wouter



More information about the Agda mailing list