2

Suppose I have a theorem

foo : (n : _) -> (f : Fin (n + 0)) -> ...
foo n f = ?goal

and it'd really benefit me if I could use f in contexts where Fin n is expected (and I really mean the precise term f instead of, say, replace (plusZeroRightNeutral n) f). How can I rewrite f's type in the environment using the appropriate lemma in addition to just rewriting the goal type?

In Agda, I'd just use a rewrite (which desugars into two parallel with-abstractions), along the lines of

foo : (n : _) -> Fin (n + 0) -> ...
foo n f rewrite plusZeroRightNeutral n = ?goal

Sure, Idris 2 has rewrite too, but it only seems to change the type of the goal, without affecting the types of the bindings in scope.

Trying to mimic what Agda does, this is what I've come up with in Idris:

foo : (n : _) -> Fin (n + 0) -> ...
foo n f with (plusZeroRightNeutral n)
  _ | eq with (plus n 0)
    _ | _ = case eq of Refl => ?goal

I'm first getting the proof of n + 0 = n. I cannot pattern-match on it yet (Idris becoming unhappy and saying Can't solve constraint between: ?n [no locals in scope] and plus ?n 0.), so what I'm doing next is with-abstracting over plus n 0. Now it becomes a single term instead of a function application, both in f and eq's types. Now I finally can pattern-match on eq (yay dependent case!), getting f : Fin n in goal's environment.

This kinda works if I have one such proof I need to apply for such "rewrite". If I have several, it gets really messy. I was hoping at least for an Agda-style parallel with, which would be a huge improvement saving some nesting and a case match, but I either couldn't figure out the syntax, or the type checker does something funny when I try with (plus n 0, plusZeroRightNeutral n).

So, is there a better way?

0xd34df00d
  • 1,496
  • 1
  • 8
  • 17

0 Answers0