如何依赖匹配具有两个元素的列表?

壁虎

我试图了解 Coq 中的依赖类型和依赖匹配,我有下面的代码,在底部我有add_pair函数,我的想法是我想接收一个包含两个元素的(依赖)列表并返回总和列表中的两个元素。由于列表的大小是在类型中编码的,我应该能够将它定义为一个总函数,但我得到一个错误,说match不是exaustive

这是代码

Module IList.
  Section Lists.
    (* o tipo generico dos elementos da lista *)
    Variable A : Set.

    (* data type da lista, recebe um nat que é
       o tamanho da lista *)
    Inductive t : nat -> Set :=
    | nil : t 0                 (* lista vazia, n = 0 *)
    | cons : forall (n : nat), A -> t n -> t (S n). (* cons de uma lista 
                                              n = n + 1 *)
    (* concatena duas listas, n = n1 + n2 *)
    Fixpoint concat n1 (ls1 : t n1) n2 (ls2 : t n2) : t (n1 + n2) :=
      match ls1 in (t n1) return (t (n1 + n2)) with
      | nil => ls2
      | cons x ls1' => cons x (concat ls1' ls2)
      end.

    (* computar o tamanho da lista é O(1) *)
    Definition length n (l : t n) : nat := n.
  End Lists.
  Arguments nil {_}.

  (* Isso aqui serve pra introduzir notações pra gente poder
     falar [1;2;3] em vez de (cons 1 (cons 2 (cons 3 nil))) *)
  Module Notations.
    Notation "a :: b" := (cons a b) (right associativity, at level 60) : list_scope.
    Notation "[ ]" := nil : list_scope.
    Notation "[ x ]" := (cons x nil) : list_scope.
    Notation "[ x ; y ; .. ; z ]" := (cons x (cons y .. (cons z nil) ..)) : list_scope.
    Open Scope list_scope.
  End Notations.
  Import Notations.

  (* Error: Non exhaustive pattern-matching: no clause found for pattern [_] *)
  Definition add_pair (l : t nat 2) : nat :=
    match l in (t _ 2) return nat with
    | (cons x (cons y nil)) => x + y
    end.

End IList.
梅文·列侬-伯特兰

确实,您提供的匹配是详尽无遗的,但是 Coq 的模式匹配算法是有限的,无法检测到它。我认为,问题在于它将嵌套模式匹配(例如您的)(您有两个 叠瓦cons)编译为一系列基本模式匹配(最多具有一个深度模式)。但是在 external 的cons分支中match,如果你没有用等式显式记录索引应该1丢失的信息——当前的算法还不够聪明,无法做到这一点。

作为避免摆弄不可能的分支、等式等的可能解决方案,我提出以下建议:

  Definition head {A n} (l : t A (S n)) : A :=
    match l with
    | cons x _ => x
    end.

  Definition tail {A n} (l : t A (S n)) : t A n :=
    match l with
      | cons _ l' => l'
    end.

  Definition add_pair (l : t nat 2) : nat :=
    head l + (head (tail l)).

作为记录,一个解决不可能的分支使用等式记录索引信息的解决方案(可能有更好的版本):

  Definition add_pair (l : t nat 2) : nat :=
    match l in (t _ m) return (m = 2) -> nat with
      | [] => fun e => ltac:(lia)
      | x :: l' => fun e =>
        match l' in (t _ m') return (m' = 1) -> nat with
        | [] => fun e' => ltac:(lia)
        | x' :: l'' => fun e' =>
          match l'' in (t _ m'') return (m'' = 0) -> nat with
          | [] => fun _ => x + x'
          | _ => fun e'' => ltac:(lia)
          end ltac:(lia)
        end ltac:(lia)
    end eq_refl.

有趣的部分是使用显式等式来记录索引的值(这些被lia策略用来丢弃不可能的分支)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何有效地找到两个列表中匹配元素的索引

如何比较两个具有不同顺序的列表?

如何枚举具有两个“ for”的列表理解?

比较两个不匹配的列表,并标识具有最大匹配元素的行

如何绑定两个具有相同结构的列表?

在比较两个列表时如何获取不匹配元素的列表?

如何比较两个具有不同长度的列表并删除一些元素?

如何将两个对象合并为具有两个元素的元组?

如何平均两个具有相同元素的数组?

如何创建具有3个元素的子列表,但是如果子列表只有一个元素,则创建两个具有2个元素的子列表?

检查两个列表是否具有公共元素

查找在Python中具有完全相同值的两个嵌套元素的列表元素

在具有匹配元素的两个列表中的每个对象上调用方法的最详细方法

Groovy比较两个列表以查找具有共同元素的列表

具有两个元素的列表

如何匹配Scala中两个列表中的元素?

提取具有两个以上字符并匹配模式的列表元素

两个元素元组的列表转换为具有相同元素的元组列表

Scala:获取具有两个限制的列表元素

如何合并两个具有字典的列表

从具有两个元素的数组中获取与匹配元素不匹配的值

如何选择具有某些两个祖先的元素?

如何计算具有两个“限制”的元素?

循环遍历具有两个匹配项的列表时如何随机选择结果

查找两个列表中匹配元素之间的元素

如何检查嵌套列表的两个元素在 Prolog 中是否具有相同的索引?

合并两个元组列表。具有两个元素的所需元组列表

具有两个依赖服务的循环依赖

如何对具有两个条件的列表进行排序