Coq`path`实现

Coq`path`实现,coq,Coq,这是一个后续问题(尽管这个问题是独立的) 我有一个简单的归纳型树(t),它有一组固定的标记(arityCode),每个标记都有固定数量的子元素。我有一个树中的路径类型(path)。我正试图实施一些操作。特别是,我希望能够在几个方向上移动光标。这看起来很简单,但我遇到了障碍 这一切都在代码中,但对我的困境有一个快速的解释:要在那里构建一个路径,我需要生成一个路径(Vector.nth v I)(其中一个子项中的路径)。但是唯一的路径构造函数(这里和那里)生成一个路径(节点cv)。因此,在某种意义上

这是一个后续问题(尽管这个问题是独立的)

我有一个简单的归纳型树(
t
),它有一组固定的标记(
arityCode
),每个标记都有固定数量的子元素。我有一个树中的路径类型(
path
)。我正试图实施一些操作。特别是,我希望能够在几个方向上移动光标。这看起来很简单,但我遇到了障碍

这一切都在代码中,但对我的困境有一个快速的解释:要在那里构建一个
路径
,我需要生成一个
路径(Vector.nth v I)
(其中一个子项中的路径)。但是唯一的
路径
构造函数(
这里
那里
)生成一个
路径(节点cv)
。因此,在某种意义上,我需要向编译器展示一条路径同时具有类型
path(Node cv)
path(Vector.nthi)
,但是Coq不够聪明,无法计算
(Vector.nth children fin)
->
节点cv
。我怎样才能让它相信这是可以的

Require Coq.Bool.Bool. Open Scope bool.
Require Coq.Strings.String. Open Scope string_scope.
Require Coq.Arith.EqNat.
Require Coq.Arith.PeanoNat. Open Scope nat_scope.
Require Coq.Arith.Peano_dec.
Require Coq.Lists.List. Open Scope list_scope.
Require Coq.Vectors.Vector. Open Scope vector_scope.
Require Fin.

Module Export LocalVectorNotations.
Notation " [ ] " := (Vector.nil _) (format "[ ]") : vector_scope.
Notation " [ x ; .. ; y ] " := (Vector.cons _ x _ .. (Vector.cons _ y _ (Vector.nil _)) ..) : vector_scope.
Notation " [ x ; y ; .. ; z ] " := (Vector.cons _ x _ (Vector.cons _ y _ .. (Vector.cons _ z _ (Vector.nil _)) ..)) : vector_scope.
End LocalVectorNotations.

Module Core.

    Module Typ.
      Set Implicit Arguments.

      Inductive arityCode : nat -> Type :=
        | Num   : arityCode 0
        | Hole  : arityCode 0
        | Arrow : arityCode 2
        | Sum   : arityCode 2
        .

      Definition codeEq (n1 n2 : nat) (l: arityCode n1) (r: arityCode n2) : bool :=
        match l, r with
          | Num, Num     => true
          | Hole, Hole   => true
          | Arrow, Arrow => true
          | Sum, Sum     => true
          | _, _         => false
        end.

      Inductive t : Type :=
        | Node : forall n, arityCode n -> Vector.t t n -> t.

      Inductive path : t -> Type :=
        | Here  : forall n (c : arityCode n) (v : Vector.t t n), path (Node c v)
        | There : forall n (c : arityCode n) (v : Vector.t t n) (i : Fin.t n),
                    path (Vector.nth v i) -> path (Node c v).

      Example node1 := Node Num [].
      Example children : Vector.t t 2 := [node1; Node Hole []].
      Example node2 := Node Arrow children.

      (* This example can also be typed simply as `path node`, but we type it this way
         to use it as a subath in the next example.
       *)
      Example here  : path (*node1*) (Vector.nth children Fin.F1) := Here _ _.
      Example there : path node2 := There _ children Fin.F1 here.

      Inductive direction : Type :=
      | Child : nat -> direction
      | PrevSibling : direction
      | NextSibling : direction
      | Parent : direction.

      Fixpoint move_in_path
               (node : t)
               (dir : direction)
               (the_path : path node)
        : option (path node) :=
        match node with
        | @Node num_children code children =>
          match the_path with
          | There _ _ i sub_path => move_in_path (Vector.nth children i) dir sub_path
          | Here _ _ =>
            match dir with
            | Child n =>
              match Fin.of_nat n num_children with
              | inleft fin_n =>
                  (* The problem:

                      The term "Here ?a@{n0:=n; n:=n0} ?t@{n0:=n; n:=n0}" has type
                      "path (Node ?a@{n0:=n; n:=n0} ?t@{n0:=n; n:=n0})" while it is expected to have type
                      "path (Vector.nth children fin_n)".

                      How can I convince Coq that `Vector.nth children fin_n`
                      has type `path (Node a t)`?
                    *)
                  let here : path (Vector.nth children fin_n) := Here _ _ in
                  let there : path node := There _ children fin_n here in
                    Some there
              | inright _ => None
              end
            | _ => None (* TODO handle other directions *)
            end
          end
        end.

    End Typ.
End Core.

您可以在此处为
定义一个智能构造函数
,该构造函数对应用它的
t
值的形状没有任何约束:

 Definition Here' (v : t) : path v := match v return path v with
   | Node c vs => Here c vs
 end.
然后你可以写:

let here : path (Vector.nth children fin_n) := Here' _ in