semantics.base.meta
Turning type class failure into subgoals
Existing Class phantom.
Existing Instance Phantom.
Existing Instance Phantom.
Example:
Typeclasses eauto := debug.
Class pointed (A : Type) := point : A.
Instance shelve_pointed {A : Type} (x : A) `{phantom A x} : pointed A | 1000 := x.
Goal forall P : Prop, P -> P.
move=> P h. apply: point. change P with (pointed P) in h. apply: point.
Qed.
This is verbatim from "Canonical structures for the working Coq user" by
Assia Mahboubi and Enrico Tassi. In ssreflect, unify is called phant_id,
but it doesn't have the extra error message.
Manually invoking unification / canonical structure inference
Require Export String.
Open Scope string_scope.
Definition unify {T1 T2 : Type} (t1 : T1) (t2 : T2) (s : option string) :=
phantom T1 t1 -> phantom T2 t2.
Notation "[find v | t1 ~ t2 ] rest" :=
(fun v (_ : unify t1 t2 None) => rest) (at level 50, only parsing)
: unify_scope.
Notation "[find v | t1 ~ t2 | msg ] rest" :=
(fun v (_ : unify t1 t2 (Some msg)) => rest) (at level 50, only parsing)
: unify_scope.
Notation "'Error: t msg" := (unify _ t (Some msg)) (at level 100, only printing)
: unify_scope.
Open Scope unify_scope.
Open Scope string_scope.
Definition unify {T1 T2 : Type} (t1 : T1) (t2 : T2) (s : option string) :=
phantom T1 t1 -> phantom T2 t2.
Notation "[find v | t1 ~ t2 ] rest" :=
(fun v (_ : unify t1 t2 None) => rest) (at level 50, only parsing)
: unify_scope.
Notation "[find v | t1 ~ t2 | msg ] rest" :=
(fun v (_ : unify t1 t2 (Some msg)) => rest) (at level 50, only parsing)
: unify_scope.
Notation "'Error: t msg" := (unify _ t (Some msg)) (at level 100, only printing)
: unify_scope.
Open Scope unify_scope.