[Agda] Two best practice questions
Andreas Abel
andreas.abel at ifi.lmu.de
Sat Dec 4 10:59:50 CET 2010
Hi Edsko,
concerning you first question, I do not see much difference between
EqOrNot and a ≡ b ⊎ b ≡ not a. The advantage of the first is that you
have more telling constructor names (same/diff instead of inj1/2 refl).
The advantage of the second is that you can use library functions for
the disjoint union. I would say the situation is not much different
from Haskell or ML where you can choose to roll your own data type or
compose it from existing ones.
In case of the second question, you do not have much of a choice. Since
the data type is negative, you are forced to use the encoding as a
recursive type-valued function instead. The fundamental difference is
that you can do induction over data types but not over types constructed
by cases and recursion. Of course, you can still do induction over
Assn, and I guess this is what you will need anyway.
Cheers,
Andreas
On 12/3/10 4:05 PM, Edsko de Vries wrote:
> Hi,
>
> I have two questions about best practice in Agda. The Agda tutorial
> spends some time on the use of views; here is one example (from
> another tutorial, on Epigram in fact):
>
> data EqOrNot : Bool -> Bool -> Set where
> same : {b : Bool} -> EqOrNot b b
> diff : {b : Bool} -> EqOrNot b (not b)
>
> eqOrNot : (a b : Bool) -> EqOrNot a b
> eqOrNot true true = same
> eqOrNot true false = diff
> eqOrNot false true = diff
> eqOrNot false false = same
>
> Such a view allows us to define a function such as xor easily:
>
> xor : (x y : Bool) -> Bool
> xor x y with eqOrNot x y
> xor x .x | same = false
> xor x .(not x) | diff = true
>
> However, why is it useful to define a custom datatype for such a view?
> We could just as easily define:
>
> eqOrNot' : (a b : Bool) -> a ≡ b ⊎ b ≡ not a
> eqOrNot' true true = inj₁ refl
> eqOrNot' true false = inj₂ refl
> eqOrNot' false true = inj₂ refl
> eqOrNot' false false = inj₁ refl
>
> without using a special datatype, and we can still define xor just as
> easily too:
>
> xor' : (x y : Bool) -> Bool
> xor' x y with eqOrNot' x y
> xor' x .x | inj₁ refl = false
> xor' x .(not x) | inj₂ refl = true
>
> What is the advantage of the first approach over the second? (From a
> pure readability perspective, to understand the type of eqOrNot we
> need to know the constructors of EqOrNot, whereas we can understand
> the type of eqOrNot' directly.)
>
> In a related question (one that motivates the first, in fact),
> consider the definition of a type that describes when an assertion is
> satisfied:
>
> _⊨_ : State -> Assn -> Set
> σ ⊨ true = ⊤
> σ ⊨ false = ⊥
> σ ⊨ (! P) = (σ I ⊨ P) -> ⊥
> -- and more clauses.. --
>
> It seems that it would be more in line with Agda practice to define
> this as a datatype instead:
>
> data _⊨_ : State -> Assn -> Set where
> sat-true : {σ : State} -> σ ⊨ true
> -- no constructor for σ ⊨ false
> sat-not : {σ : State} -> {P : Assn} -> ((σ ⊨ P) -> ⊥) -> σ ⊨ (! P)
> -- and more constructors.. --
>
> but this datatype definition is rejected, since there is a negative
> occurrence in the definition for ! P -- even though this datatype is
> clearly well-founded (defined by induction on the assertion). If there
> are good reasons, above, to choose eqOrNot (using a special datatype)
> over eqOrNot', then is a definition for ⊨ as a function instead of a
> datatype going to get me into trouble later?
>
> Thanks,
>
> Edsko
> _______________________________________________
> Agda mailing list
> Agda at lists.chalmers.se
> https://lists.chalmers.se/mailman/listinfo/agda
>
--
Andreas Abel <>< Du bist der geliebte Mensch.
Theoretical Computer Science, University of Munich
Oettingenstr. 67, D-80538 Munich, GERMANY
andreas.abel at ifi.lmu.de
http://www2.tcs.ifi.lmu.de/~abel/
More information about the Agda
mailing list