[Agda] Positivity checker
Nils Anders Danielsson
nad at Cs.Nott.AC.UK
Mon Dec 8 10:10:45 CET 2008
On 2008-12-07 21:45, Peter Dybjer wrote:
>
> The reason why this data type is ok, is because it is isomorphic to the
> corresponding family defined by induction on n.
>
> But what is the induction principle? Except induction on n?
Do you suggest that one could inadvertently introduce new (stronger)
induction principles by accepting this type (or similar types)?
> On Dec 5, 2008, at 4:53 PM, Nils Anders Danielsson wrote:
>
>> On 2008-12-04 17:31, Wouter Swierstra wrote:
>>
>>> but I'd much rather work with data (the example I have in mind is
>>> pretty complicated).
>>
>> Yes.
>
> Why?
We have already had this discussion:
http://appserv.cs.chalmers.se/users/ulfn/wiki/agda.php?n=Main.InductiveFamilies
The list archives may be more persistent than the wiki, so I include
parts of my contribution to that discussion:
The Vec example has been discussed above. While it is possible to
define vectors using a function, do we want to do that? The Vec type
is often seen as a more precise version of the List type, and this is
most easily seen when they are both defined as data. [If the only two
choices are the standard data type and the standard Set-valued
function.] I don’t think we should scare away functional programmers,
who are familiar with data types (and now also GADTs), by defining Vec
in a different way from List.
Furthermore, when functions are defined by explicit recursion,
functions defined over Vec defined as a function are quite a bit more
verbose than those defined over Vec defined as an inductive family:
map : forall {a b n} -> (a -> b) -> Vec a n -> Vec b n
map f [] = []
map f (x ∷ xs) = f x ∷ map f xs
map' : forall {a b} n -> (a -> b) -> Vec' a n -> Vec' b n
map' zero f tt = tt
map' (suc n) f (x , xs) = f x , map' n f xs
It also feels wrong to pattern match on a pair, when I want to pattern
match on a cons. This can be worked around as follows (based on code
written by Ulf):
data Nil : Set where
nil : Nil
data Cons (A As : Set) : Set where
_::_ : A -> As -> Cons A As
Vec : Set -> Nat -> Set
Vec A zero = Nil
Vec A (suc n) = Cons A (Vec A n)
map : forall {a b} n -> (a -> b) -> Vec a n -> Vec b n
map zero f nil = nil
map (suc n) f (x :: xs) = f x :: map n f xs
Finally Vec defined as a function has a tendency to be harder to work
with, since the definition unfolds when the natural number is not
neutral. There is a workaround for this as well, adding even more
overhead (code by Ulf):
-- When defining types by recursion it is sometimes difficult to
-- infer implicit arguments. This module illustrates the problem and
-- shows how to get around it for the example of vectors of a given
-- length.
module Introduction.Data.ByRecursion where
data Nat : Set where
zero : Nat
suc : Nat -> Nat
data Nil : Set where
nil' : Nil
data Cons (A As : Set) : Set where
_::'_ : A -> As -> Cons A As
mutual
Vec' : Set -> Nat -> Set
Vec' A zero = Nil
Vec' A (suc n) = Cons A (Vec A n)
data Vec (A : Set)(n : Nat) : Set where
vec : Vec' A n -> Vec A n
nil : {A : Set} -> Vec A zero
nil = vec nil'
_::_ : {A : Set}{n : Nat} -> A -> Vec A n -> Vec A (suc n)
x :: xs = vec (x ::' xs)
map : {n : Nat}{A B : Set} -> (A -> B) -> Vec A n -> Vec B n
map {zero} f (vec nil') = nil
map {suc n} f (vec (x ::' xs)) = f x :: map f xs
To summarise: In Agda it is more convenient to program using data types.
--
/NAD
This message has been checked for viruses but the contents of an attachment
may still contain software viruses, which could damage your computer system:
you are advised to perform your own checks. Email communications with the
University of Nottingham may be monitored as permitted by UK legislation.
More information about the Agda
mailing list