[Agda] Records and irrelevant fields
Andreas Abel
andreas.abel at ifi.lmu.de
Thu Sep 23 14:22:53 CEST 2010
On Sep 22, 2010, at 12:42 AM, Dan Doel wrote:
> On Tuesday 21 September 2010 3:13:18 am Andreas Abel wrote:
>
>> However, I think there is no problem with Squash, because there is
>> always exactly one match, whereas with equality types there is at
>> most
>> one match, and it has a side information that two things are
>> declaratively equal.
>
> Having thought about this some more, I came to the conclusion that
> it is
> indeed just another statement that double-irrelevance is the same as
> irrelevance, or that Squash is a monad. It makes the following
> equivalent:
>
> Squash A => B
> Squash A -> B
> A => B
>
> at least in the non-dependent cases. And that first case is also the
> same as
>
> Squash (Squash A) -> B
>
> I'm willing to bet that this case is sound. The question then
> becomes: how
> does one decide when it's safe (Squash) and when it isn't
> (equality)? Or are a
> couple special cases (Squash and Unit alikes) enough?
Well, if you look at the definition of equality (allow me to stick to
MiniAgda syntax)
data Eq (A : Set)(a : A) : A -> Set
{ refl : Eq A a a
}
then you see that you are dealing with a non-linear pattern inductive
family (quite a mouthful ;-)). This is to say that the arguments to
Eq in the constructor type(s) are all patterns, but non-linear. If
you construct an Eq A a b by refl, you are putting the "side
information" in that a and b are definitionally equal, but this side
information is not just a component of the structure you are creating
(in this case the "structure" refl you create carries in fact no
structure).
How to handle this side information I am not 100% clear. In MiniAgda,
I allow also irrelevant matches against refl, but this leads to
inability to erase at compile-time. I still have proof irrelevance,
but from a performance aspect it would be nice to actually throw away
more during compile-time.
If one retreats to the "safer" EPTS with compile-time erasure, but
still wants proof irrelevance for equality, the we cannot allow all
these legal MiniAgda typings for subst, for instance.
0) subst : [A : Set] -> [P : A -> Set] -> (a, b : A) -> Id A a b -> P
a -> P b
1) subst : [A : Set] -> [P : A -> Set] -> [a, b : A] -> Id A a b -> P
a -> P b
2) subst : [A : Set] -> [P : A -> Set] -> (a, b : A) -> [Id A a b] ->
P a -> P b
3) subst : [A : Set] -> [P : A -> Set] -> [a, b : A] -> [Id A a b] ->
P a -> P b
subst A P a .a (refl .A .a) h = h
0 is uncontroversial. 1 is the EPTS one and likewise harmless, but it
fails proof irrelevance, because
subst A P a a p h
does not reduce for p != refl. Note that 0 leaves the option for
proof irrelevance, because a and b are not erased, thus instead of
checking p for refl you can check a and b for equality.
2 looks a bit weird at first glance, but it is inessence what is
described in Benjamin Werner's 2008 paper on proof irr. Here, we
never check p for refl, but always compare a and b for equality. This
looks like a systematic solution, but in terms of performance it could
be cheaper to check p for refl. Who knows? There might be a lot of
computation necessary to normalize p to refl, but likewise to
normalize both a and b to check for equality.
3 does not permit compile-time erasure, that's the current situation
in MiniAgda.
How can we change the type system to dissallow 1-3? Forbidding
irrelevant matching on non-linear pattern inductive families would
rule out 2 and 3. Forbidding 1 could be done by saying a and b are
relevant in Id A a b even on the type level. This, of course is not
EPTS, it is more like Pfenning's system, but not quite, ... see below.
> On an unrelated note, I studied a bit more of Pfenning's modal type
> theory in
> the paper I mentioned earlier. I can find no difference in the
> context reset
> rules between his proof irrelevant modality and the modality in
> EPTS. The
> difference between the two theories has to do with some of the type
> formation
> rules. For instance, Pfenning gives pi formation as:
>
> G |- A * Type G , x * A |- B : Type
> --------------------------------------
> G |- (Pi x * A. B) : Type
>
> where * stands in for any particular modality. In an EPTS, it's:
>
> G |- A :r Type G , x :r A |- B :r Type
> ---------------------------------------
> G |- (Pi x * A. B) :r Type
>
> * again standing in for either :r or :c, to similarize the notation.
This is THE difference. ;-)
> I don't actually know how different this makes the two theories, but
> the
> irrelevant modalities in either are going to be pretty similar. The
> EPTS
> thesis states that the difference between the two is their desire to
> treat
> erasability as extrinsic to to the type, while Pfenning's models
> intrinsic
> erasability---for instance, x must be erasable from the type of B in
> Pfenning's system (and the judgment of the type of A has a
> corresponding
> modality), whereas it's relevant in the EPTS.
The difference become apparent in the standard example for dependent
types ;-).
vcons : [n : Nat] -> A -> Vec A n -> Vec A (suc n)
is not well-typed in Pfenning's System unless n is irrelevant in Vec
Vec : (A : Set) -> [n : Nat] -> Set
but this means that Vec A zero = Vec A (suc n) which is not desirable.
Pfennings system is good for *proof* irrelevance only, since he has
(x : Squash A) -> B x isomorphic to [x : A] -> B x
not only
Squash A -> B isomorphic to [A] -> B
as in EPTS.
This is why I said Pfenning's system was "boring" (maybe it I should
say "not good enough").
> I guess that might mean that EPTSes are quite close to the LiCS
> stuff you
> mentioned earlier.
By "LiCS" I meant exactly Pfenning's paper you just studied.
> I've also come to a tentative conclusion that weakness of
> elimination is kind
> of important to the abstraction guarantees of, say, modules. We
> might have a
> signature like:
>
> mod : exists T : Set.
> T * (T -> T) * (forall R. R -> (R -> R) -> T -> R)
>
> and a key aspect of the abstraction is that T must always be opaque
> outside of
> the definition of 'mod', even if we happen to know what the
> definition of mod
> is, I think (that is, mod is some particular definition, not some
> variable
> we've quantified over). Even if we are only able to project out T at
> compile
> time, if (proj1 mod) isn't opaque, then we are no longer required to
> program
> to the interface exposed by the module.
You mean that if you had the projections (mod.T is not exactly right,
but in essence)
Z : mod -> mod.T
S : mod -> mod.T -> mod.T
iter : ...
Then
Z nat_mod : Nat
S nat_mod : Nat -> Nat
I see, then compile-time erasure is again not possible.
Thanks, this shows that my idea of first-class irrefutable patterns
and erasure is flawed.
Indeed, it does not work:
snd : (exist a b : Exists A B) -> B a
is illtyped. We have to show
(exists a b : Exists A B) |- B a : Set
which simplifies to
[a : A], b : B a |- B a : Set
which gives a type error since a is irrelevant and cannot appear in B
a. (Also the context is ill-formed).
So I should drop this idea, at least for compile-time erasure.
> In this sense, inductives with irrelevant fields are kind of like
> units of
> erasure. We can't project the A out of an Exists A P, except as a
> Squash A,
> because it's already been erased, to enforce the abstraction above.
> Of course,
> I can see this not necessarily being what is always desired. You may
> sometimes
> want a compile/runtime devide where compile time things are always
> transparent
> at compile time. Perhaps it's possible to incorporate both.
Cheers,
Andreas
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