Require Import String.
Require Import Ascii.
Require Import List.
Inductive optionE (X:Type) : Type :=
| SomeE : X -> optionE X
| NoneE : string -> optionE X.
Implicit Arguments SomeE [[X]].
Implicit Arguments NoneE [[X]].
Inductive sublist {A : Set} : list A -> list A -> Prop :=
| sl_tail : forall (c : A) l, sublist l (c::l)
| sl_cons : forall (c : A) l' l, sublist l' l -> sublist l' (c::l).
Definition parser (T : Type) :=
forall l : list ascii, optionE (T * {l' : list ascii | sublist l' l}).
(* This works. And I don't understand why. The type checker seems to be able to figure out that xs = c::t. *)
Definition foo {T : Type} (f : T) : parser T :=
fun xs => match xs with
| nil => NoneE "End of token stream"
| (c::t) => SomeE (f, exist _ t (sl_tail c t))
end.
(* And this one doesn't. And given that the above works, I don't understand why this doesn't. *)
Definition bar (f : T) : parser T :=
fun xs => match xs with
| nil => NoneE "End of token stream"
| (c::t) => SomeE (f, exist _ t (sl_tail c t))
end.
(* And this is how I would like to actually write this code: create a placeholder at the point of
proof, and use the tactic language to write down the proof. Explicitly constructing a proof
is tedious, but there seems to be no way around it when using dependent types. *)
Definition baz (f : T) : parser T :=
fun xs => match xs with
| nil => NoneE "End of token stream"
| (c::t) => SomeE (f, exist _ t _)
end.
Proof
apply sl_tail. (* or whatever *)
Qed.