如何证明复杂表达式和“真”之间的命题相等?

如何解决如何证明复杂表达式和“真”之间的命题相等?

我有一些看起来像这样的代码:

allLessThan : Ord t => (v1 : Vect n t) -> (v2 : Vect n t) -> Bool
allLessThan v1 v2 = all (\(x,y) => x < y) (zip v1 v2)

unravelIndexUnsafe : (order : ArrayOrder) ->
                     (shape : ArrayShape (S n)) ->
                     (position : Vect (S n) Nat) ->
                     Nat
unravelIndexUnsafe order shape position = ?someImplementation

unravelIndexSafe : (order : ArrayOrder) ->
                   (shape : ArrayShape (S n)) ->
                   (position : Vect (S n) Nat) ->
                   {auto 0 prfPositionValid : (allLessThan position shape) = True} ->
                   Nat
unravelIndexSafe order shape position = unravelIndexUnsafe order shape position

unravelIndex : (order : ArrayOrder) ->
               (shape : ArrayShape (S n)) ->
               (position : Vect (S n) Nat) ->
               Maybe Nat
unravelIndex order shape position =
  case allLessThan position shape of
    True => Just $ unravelIndexSafe order shape position
    False => Nothing

我省略了 unravelIndexUnsafe 的实现,我认为这与问题无关。

我在 unravelIndex 的定义中遇到类型错误,说它找不到 prfPositionValidunravelIndexSafe* 一起使用的实现。

这让我感到惊讶,因为我在 allLessThan position shape 上明确区分大小写,并且只在 unravelIndexSafe 分支中调用 True。我希望 Idris 能够从这些信息中推断出命题 (allLessThan position shape) = True 成立。

有没有直接的方法来解决这个问题?也许我可以显式构造并传递 prfPositionValid 隐式参数?或者我应该在这里使用完全不同的方法吗?我是否需要以不同的方式表达 prfPositionValidallLessThan?我需要rewrite什么吗?

* 更准确地说,它找不到prfPositionValid这个可怕的“完全扩展”版本的实现:

foldl (\acc,elem => acc && Delay (case block in allLessThan (S n) Nat (MkOrd (\{arg:354},{arg:355} => compare arg arg) (\{arg:356},{arg:357} => == (compare arg arg) LT) (\{arg:358},{arg:359} => == (compare arg arg) GT) (\{arg:360},{arg:361} => not (== (compare arg arg) GT)) (\{arg:362},{arg:363} => not (== (compare arg arg) LT)) (\{arg:364},{arg:365} => if == (compare arg arg) GT then x else y) (\{arg:366},{arg:367} => if == (compare arg arg) LT then x else y)) shape position elem)) True (zipWith (\{__leftTupleSection:0},{__infixTupleSection:0} => (__leftTupleSection,__infixTupleSection)) position shape) = True

解决方法

解决方案:使用可判定等式

答案是使用“可判定的平等”,因为伊德里斯不像人类那么聪明。

请注意,特殊的 = 语法等效于内置运算符 (===),它等效于类型 EqualEqual 的构造函数是 Refl。为了证明 Equal a b 形式的命题,Idris 必须能够弄清楚 ab 实际上是同一件事(称之​​为 c)。如果您可以使用类型 Refl c 调用 Equal a b,那么您已经证明了 Equal a b。相反,获得 Equal a b 实例的唯一方法是调用 Refl c

Idris 2 不能通过 case-splitting 推断命题相等。我,一个人类,知道我们试图证明 allLessThan position shape 在命题上等于 True。在 Idris 中,这意味着我们希望能够编写 Refl TrueallLessThan position shape 上的大小写拆分确实会导致 Bool,但这本身并不构成对 Refl True 类型的 Equal (allLessThan position shape) True 调用。因此,原始代码中的大小写拆分不足以让 Idris 推断出 Equal (allLessThan position shape) True 的证明。

我们知道 allLessThan position shape 是一个可判定谓词,因此我们可以使用 decEq 来获得我们需要的证明/实现。因此我们可以将 unravelIndex 写成:

unravelIndex : (order : ArrayOrder) ->
               (shape : ArrayShape (S n)) ->
               (position : Vect (S n) Nat) ->
               Maybe Nat
unravelIndex order shape position =
  case decEq (allLessThan position shape) True of
    Yes proof => Just $ unravelIndexSafe order shape position
    No contra => Nothing

proof 中的 Yes proof 正是我们要寻找的 Refl True,它实现了 Equal (allLessThan position shape) True。因此,Idris 将能够为 prfPositionValid 自动隐式推断一个值,因为在范围内可以使用正确类型的值。

您也可以用 _ 代替 proofcontra,因为证明在代码中的任何地方都没有明确使用,因此它们不需要名称。

重构

请注意,此 allLessThan position shape 有点临时。特别是,说明属性的条件需要程序员记住特定的表达式。但是我们想编写一个更简洁的 API,其中程序员可以调用函数 isPositionValidForShape 来检查有效性,并使用类型 IndexValidForShape 来表示“有效”状态。

allLessThan : Ord t => (v1 : Vect n t) -> (v2 : Vect n t) -> Bool
allLessThan v1 v2 = all (\(x,y) => x < y) (zip v1 v2)

IndexValidForShape : (shape : ArrayShape ndim) ->
                     (position : ArrayIndex ndim) ->
                     Type
IndexValidForShape shape position =
  let isValid = allLessThan position shape
  in Equal isValid True

isIndexValidForShape : (shape : ArrayShape (S n)) ->
                       (position : ArrayIndex (S n)) ->
                       Dec (IndexValidForShape shape position)
isIndexValidForShape shape position =
  decEq (allLessThan position shape) True

unravelIndexUnsafe : (order : ArrayOrder) ->
                     (shape : ArrayShape (S n)) ->
                     (position : ArrayIndex (S n)) ->
                     Nat
unravelIndexUnsafe order shape position =
  sum $ zipWith (*) (strides order shape) position

unravelIndexSafe : (order : ArrayOrder) ->
                   (shape : ArrayShape (S n)) ->
                   (position : ArrayIndex (S n)) ->
                   {auto 0 prfIndexValid : IndexValidForShape shape position} ->
                   Nat
unravelIndexSafe order shape position =
  unravelIndexUnsafe order shape position

unravelIndex : (order : ArrayOrder) ->
               (shape : ArrayShape (S n)) ->
               (position : ArrayIndex (S n)) ->
               Maybe Nat
unravelIndex order shape position =
  case isIndexValidForShape shape position of
    Yes _ => Just $ unravelIndexSafe order shape position
    No _ => Nothing

现在,最终用户不必知道或关心 IndexValidForShape 究竟意味着什么,或者您需要使用 allLessThan 来检查它。

事实上,我们现在可以改变索引“有效”的含义,主要是不影响下游代码用户;也许我想实施额外的检查,只有在我发现逻辑错误后才能了解。

或者,应该可以将 IndexValidForShape 重新设计为更加“结构化”,其中您可以归纳地定义表示所需属性的数据类型。例如,请参阅类型驱动开发第 9 章中的 Data.Vect.Elem 及其说明。

词汇表

  • decidable:“如果您始终可以说出该属性是否适用于某些特定值,那么该属性就是可判定的”(引自类型驱动开发,第 245 页)。
  • Dec:表示可判定属性有效性的类型。它的构造函数是:
    • Yes : property -> Dec property - property 持有。
    • No : (property -> Void) -> Dec property - property 是一个矛盾。
  • DecEq:数据类型的接口,其相等性可以确定为可判定属性。
  • decEqDecEq 的方法,用于确定两个事物是否可确定相等。它的类型是 DecEq t => (x1 : t) -> (x2 : t) -> Dec (Equal x1 x2)

参考资料和进一步阅读

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 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-