如何存在模式匹配以转换证明

如何解决如何存在模式匹配以转换证明

我正在处理 coq,我正在尝试创建一个函数,该函数可用于在列表中查找某些内容并返回与之相关的证明,证明指定的元素在列表中。

就我而言,我有一个元组列表,我想根据元组的第一个元素进行查找。

所以首先我定义了一个 { "total": 9,"rows": [ { "id": 0,"name": "jersey","birthday": "01.05.1995","college": "NEU" },{ "id": 1,{ "id": 2,{ "id": 3,{ "id": 4,{ "id": 5,{ "id": 6,{ "id": 7,{ "id": 8,{ "id": 9,"college": "NEU" } ] } 归纳谓词来证明一个元素在列表中。这有两种情况。元素要么在列表的头部,要么在尾部。

assoc

然后我定义了一个 Inductive assoc (A : Set) (B : Set) : list (A * B) -> A -> B -> Prop := | assocHead : forall (l : list (A * B)) (a : A) (b : B),assoc A B (cons (a,b) l) a b | assocTail : forall (l : list (A * B)) (a x : A) (b y : B),assoc A B l a b -> assoc A B ((x,y) :: l) a b. 函数,该函数给出了一个元组列表、一个第一个元素和一个相等谓词,返回 None 或 Some 以及查找的元素和该元素在列表中的证明。

>
lookup

上面写的方式编译得很好。但我不知道如何使用列表 Program Fixpoint lookup (A : Set) (B : Set) (dec : (forall x y : A,{x = y} + {x <> y})) (l : list (A * B)) (a : A) {struct l} : option {b : B | assoc A B l a b} := match l with | [] => None | (pair v t) :: tl => if dec v a then (Some (exist (assoc A B ((pair v t) :: tl) a) t (assocHead A B tl a t))) else match (lookup A B dec tl a) with -- In the case below we have proven it's in the -- tail of the list. -- How to use that to create new proof with assocTail? | Some (exist _ _ _) => None | None => None end end. 中的证明来创建它在总列表中的新证明。我在 tl 的第三个参数中尝试了诸如模式匹配之类的各种方法,但我永远无法让它工作。

感谢任何帮助!

解决方法

首先,像这样写assoc可能更好

Inductive assoc {A B : Type} (k : A) (v : B) : list (A * B) -> Prop :=
| assoc_head : forall l,assoc k v ((k,v) :: l)
| assoc_tail : forall l x,assoc k v l -> assoc k v (x :: l).
Arguments assoc_head {A B} {k v},{A B} k v,A B k v.
Arguments assoc_tail {A B} {k v} {l},{A B} {k v} l,{A B} k v l,A B k v l.

基本上,: 左边的东西越多,处理类型就越容易(参数越多,索引越少)。我实际上会更进一步写

Inductive elem {A : Type} (x : A) : list A -> Prop :=
| in_here : forall l,elem x (x :: l)
| in_there : forall l y,elem x l -> elem x (y :: l).
Definition assoc {A B : Type} (k : A) (v : B) l := elem (k,v) l.

但这已经偏离了轨道。

无论如何,您无需检查代码中 exists 的第三个参数。你只要把它交给assoc_tail。完成。

#[program] Fixpoint lookup
  {A B : Type} (dec : forall x y : A,{x = y} + {x <> y})
  (l : list (A * B)) (k : A) {struct l}
: option {v : B | assoc k v l}
:=
  match l with
  | [] => None
  | (k',v') as h :: l =>
    if dec k' k (* writing the first argument to exist is usually just clutter *)
      then Some (exist _ v' (assoc_head k' v' l))
      else
        match lookup dec l k with
        | Some (exist _ v prf) => Some (exist _ v (assoc_tail h prf))
        | None => None
        end
  end.

请注意,Program 的部分神奇之处在于它应该让您编写实际的程序,而不必先担心证明部分。特别是,你应该想象像 x : {v : B | assoc k v l} 这样的细化类型的值只是 x : B,然后再处理细化的证明部分。

#[program] Fixpoint lookup
  {A B : Type} (dec : forall x y : A,v') :: l =>
    if dec k' k
      then Some v'
      else
        match lookup dec l k with (* looks weird but is still necessary *)
        | Some v => Some v
        | None => None
        end
  end.
Solve Obligations with program_simpl; now constructor.

关于这一点,lookup 可以做得比仅仅返回一个 option 更好!

#[local] Hint Constructors assoc : core.
#[local] Unset Program Cases.

#[program] Fixpoint lookup
  {A B : Type} (dec : forall x y : A,{x = y} + {x <> y})
  (l : list (A * B)) (k : A) {struct l}
: {v : B | assoc k v l} + {~exists v : B,assoc k v l}
:=
  match l with
  | [] => inright _ (* Underscores as an "escape hatch" to an obligation *)
  | (k',v') :: l =>
    if dec k' k
      then inleft v'
      else
        match lookup dec l k with
        | inleft v => inleft v
        | inright no => inright _
        end
  end.
Next Obligation.
  intros [v no].
  inversion no.
Qed.
Next Obligation.
  intros [v nono].
  inversion nono as [? | ? ? nono']; eauto.
Qed.
,

在递归调用中对 exist 对进行模式匹配后,您知道该对的第一个组件也是结果的第一个组件。然后第二个组成部分是您可以作为单独义务填写的证明。

match lookup ... with
| Some (exist _ b _) => Some (exist _ b _ (* this underscore becomes an obligation *))
| None => None
end

这允许 Program Definition 命令完成,然后您必须证明有义务(引理)实际完成该定义。请务必使用 Defined 而不是 Qed 终止证明,因为保护检查器以某种方式需要您的证明透明。

Next Obligation.
  (* finish the proof *)
Defined.

Program Fixpoint lookup
  (A : Set)
  (B : Set)
  (dec : (forall x y : A,{x = y} + {x <> y}))
  (l : list (A * B))
  (a : A)
  {struct l}
  : option {b : B | assoc A B l a b}
:= match l with
   | [] => None
   | (pair v t) :: tl =>
     if dec v a
     then (Some (exist (assoc A B ((pair v t) :: tl) a) t (assocHead A B tl a t)))
     else match (lookup A B dec tl a) with
          | Some (exist _ b _) => Some (exist _ b _)
          | None => None
          end
   end.

Next Obligation.
  apply assocTail.
  assumption.
Defined.
,

库中已经有一个谓词 In 来指定列表是否包含元素,因此您实际上不需要定义新的 assoc 谓词。

您可以尝试使用 refine 策略,我发现它对逐步构建术语非常有帮助。这有点像使用 Program 但感觉没那么神奇。您尽可能多地写下术语(即 destruct 将生成的匹配语句),并在您想要获得证明义务的地方放入 _。您可以对义务使用证明策略,并查看您建立的术语。这可能很有启发性。

我最终完成了这个程序:

Require Import List.

Fixpoint lookup {A B} (dec: forall (a a':A),{a=a'}+{a<>a'})
         (l:list (A*B)) (a:A) {struct l} : option {b | In (a,b) l}.
  refine (
      match l with
      | nil => None
      | cons (a',b) l' =>
        match dec a a' with
        | left _ y => Some (exist _ b (or_introl _))
        | right _ y  =>
          match lookup _ _ dec l' a with
          | None => None
          | Some (exist _ b' H') => Some (exist _ b' (or_intror H'))
          end
        end
      end).
  congruence.
Defined.

请注意,出于教学原因,我在该术语中留下了一个 _,这是通过 congruence 策略处理的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-