You probably want to define the following function (even if you annotate it correctly, you [le_S mnx] do not have the type you need):
Fixpoint lesseq (mn : nat) : option (m <= n) := match n with | 0 => match m with | 0 => Some (le_n 0) | S m0 => None end | S p => match lesseq mp with | Some l => Some (le_S mpl) | None => None end end.
But, as you noticed, typechecker is not smart enough to guess the new context when you destroy the variable that appears in the type of result. You must annotate the match as follows:
Fixpoint lesseq (mn : nat) : option (m <= n) := match n return (option (m <= n)) with | 0 => match m return (option (m <= 0)) with | 0 => Some (le_n 0) | S m0 => None end | S p => match lesseq mp with | Some l => Some (le_S mpl) | None => None end end.
See the reference guide if you really want to understand how pattern matching works with dependent types. If you donβt feel brave enough to do this, you will prefer to use tactical mechanisms to create your evidence (refinement tactics are a great tool for this).
Definition lesseq mn : option (m <= n). refine (fix lesseq (m : nat) (n : nat) {struct n} := _). destruct n. destruct m. apply Some; apply le_n. apply None. destruct (lesseq mn). apply Some. apply le_S. assumption. apply None. Defined.
By the way, I do not think that your function will be really useful (even if it is a good idea), because you will need to prove the following lemma: Lemma lesseq_complete: forall mn, lesseq mn <> None β m> n.
This is why people use Coq.Arith.Compare_dec. Have some fun.
source share