Coq: a single notation for multiple constructors

。_饼干妹妹 提交于 2019-12-06 02:16:36

You can create a typeclass with the constructors as instances and let the instance resolution mechanism infer the constructor to call for you:

Class A_const (X:Type) : Type :=
  a_const : X -> A.
Instance A_const_c : A_const C := c.
Instance A_const_d : A_const D := d.

Check a_const c1.
Check a_const d2.

By the way, with Coq 8.5, if you really want a notation ' x to result in the exact constructor applied to x, rather than e.g. @a_const C A_const_c c1, then you can use ltac-terms to accomplish that:

Notation "' x" := ltac:(match constr:(a_const x) with
                        | @a_const _ ?f _ =>
                          let unfolded := (eval unfold f in f) in
                          exact (unfolded x)
                        end) (at level 0).
Check 'c1. (* c c1 : A *)
Check 'd2. (* d d2 : A *)

In fact, the idea of using an ltac-term leads to an entirely different solution from the other one I posted:

Notation "' x" := ltac:(let T := (type of x) in
                        let T' := (eval hnf in T) in
                        match T' with
                        | C => exact (c x)
                        | D => exact (d x)
                        end) (at level 0).
Check 'c1. (* c c1 : A *)
Check 'd2. (* d d2 : A *)

(Here the eval hnf part lets it work even if the type of the argument isn't syntactically equal to C or D, but it does reduce to one of them.)

Apparently, it's easy:

Notation "' x" := ((_:_->A) x) (at level 19).
Check 'c1. (*' c1 : A*)
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!