0

A piece of code here:

-- transitivity
trans : {A : Set} {x y z : A} -> x == y -> y == z -> x == z
trans refl refl = refl

union-pair' : {A : Set} -> (m n : S {A}) -> (x : A) ->
                           (ismember (set-union (set-pair m n)) x) == (ismember (union m n) x)
union-pair' m n x with ismember m x | ismember n x | ismember (set-union (set-pair m n)) x
union-pair' : {A : Set} -> (m n : S {A}) -> (x : A) ->
                       (ismember (set-union (set-pair m n)) x) == (ismember (union m n) x)
union-pair' m n x with ismember m x | ismember n x | ismember (set-union (set-pair m n)) x
...                  | false | false | false = trans {x = ismember (set-union (set-pair m n)) x} {y = false}
                                                     refl -- line #102
                                                     (union-match m n x)
-- more code available on request, although I can't see why that would matter

produces an error:

code.agda:102,54-58
(ismember (set-union (set-pair m n)) x) != false of type Bool
when checking that the expression refl has type
ismember (set-union (set-pair m n)) x == false

I have a with-statement, which establishes exactly the fact that ismember (set-union (set-pair m n)) x is false. Why can it not establish that it is false?


Ok, I can even see some known issues https://agda.readthedocs.io/en/v2.5.2/language/with-abstraction.html#ill-typed-with-abstractions but still none the wiser as to how to pattern match then.

Sassa NF
  • 5,306
  • 15
  • 22

1 Answers1

6

It looks like you need to remember the fact that the following expression

ismember (set-union (set-pair m n)) x

is indeed equal to

false

This is a very common problem that comes from the way the 'with' construct works. By default, you don't have access to the proof element that connects the element on which you pattern match with the result of the pattern matching, that is, in your example, an element of type:

ismember (set-union (set-pair m n)) x == false

In order to get an element of this type, you need to use the 'inspect' idiom that is defined alongside the propositional equality in the standard library. More concretely, this means you'll have to add a new element to your pattern matching as follows:

... | ismember (set-union (set-pair m n)) x | inspect (ismember (set-union (set-pair m n)) x

This will result in you having access both to 'false' and the proof element you require. For more information about the inspect idiom, see :

  • The wiki page on the with-abtraction : https://agda.readthedocs.io/en/v2.6.0.1/language/with-abstraction.html
  • The file PropositionalEquality.agda in the standard library, which provides the idiom as well as a quick description of how to use it
  • The file README/Inspect.agda in the standard library as well which provides a complete example on how and when to use the inspect idiom
MrO
  • 1,291
  • 7
  • 14
  • Thanks! This is similar to what I came up with, although my approach is much more clunky. In the end I created a decidable `(_==?_)` type, which either provides a proof `(ismember s x == true)`, or proves `(ismember s x == true)` is absurd, then we can go from there. – Sassa NF Nov 06 '19 at 10:04
  • 2
    As a side note, it looks to me that you could have modeled your problem better so that you don't have to use such techniques. For instance, if you had made 'ismember' a predicate instead of a function which returns a boolean, it seems that your development would be much more convenient and elegant. If you need help doing so, and if you feel like I'm right, don't hesitate to ask another question and link it to me here. – MrO Nov 06 '19 at 12:40
  • Right, and the confusing bit in the documentation during my earlier reading of the page you quote, is the seeming difference `with` vs `rewrite`: `One limitation of the rewrite construction is that you cannot do further pattern matching on the arguments after the rewrite, since everything happens in a single clause. You can however do with-abstractions after the rewrite.` - which to me implied that `with` does not lose the connection between the pattern and the expression it has been produced from. – Sassa NF Nov 06 '19 at 15:04
  • Thanks for the offer. I want first to get a working version, no matter how hard or non-canonical it may look - just because then I encounter quirks that help me understand the available mechanisms better. I will want to rewrite that in a better style. – Sassa NF Nov 06 '19 at 15:06
  • The other confusing bit is the difference between `with`-abstracting for an expression that is used in some intermediate goal and the final goal - eg the particularly frustrating part was that agda doesn't mind constructing a `refl` for `ismember m x == true` in `ismember? : {A : Set} -> (m : S {A}) (x : A) -> (ismember m x) ==? true` - here, as I understand now, the difference is that `with`-abstraction rewrites all available occurrences of `ismember m x` - including that in the return type. In the example an intermediate goal of type `ismember m x == true` is not visible at rewrite time. – Sassa NF Nov 06 '19 at 15:14