- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我有以下类型 typ
代表 bool 或 nat:
Inductive typ : Type := TB | TN.
我还有一个函数可以从 typ
列表和结果类型中提取实际函数类型:
Fixpoint get_types (s: seq typ) (result_type: Type) : Type :=
match s with
| nil => result_type
| x :: xs => match x with
| TN => nat -> get_types xs result_type
| TB => bool -> get_types xs result_type
end
end.
Example get_types_works : get_types (TB :: TN :: nil) nat = bool -> nat -> nat.
Proof. by []. Qed.
现在,我有另一个函数,它将 typ
的列表 s
和 get_types s
类型的函数作为输入:
Fixpoint app (s: seq typ) (constructor: get_types s nat) : nat :=
match s with
| nil => 2 (* Not properly handling empty list case for now *)
| TB :: nil => constructor true
| TN :: nil => constructor 2
| TB :: xs => app xs (constructor true)
| TN :: xs => app xs (constructor 2)
end.
在 | 行定义上述函数失败。 TB::nil => 构造函数 true
with:
Illegal application (Non-functional construction):
The expression "constructor" of type "get_types s nat" cannot be applied to the term
"true" : "bool"
鉴于我们在这里知道 get_types s nat
的类型应该是 bool -> nat
,因为 s
的值是 TB::nil
,我想知道是否有办法让 Coq 意识到这一点,以便可以定义上述函数?
如果不是,这是 Coq 的限制还是同样适用于其他依赖类型的语言?
编辑:就上下文而言,这不是我要解决的原始问题;这是一个精简版本,显示了我在类型系统上遇到的问题。在实际版本中,不是硬编码 2
和 true
,类似 typ
的数据结构还携带数据索引以从内存中解析切片和验证功能。 app
的目标是一个函数,它接受这样的 typ
列表、切片和包含这些类型的记录的构造函数,然后构造该记录的实例从要解析的类型的索引中提取,如果任何验证失败,则返回 None
。
最佳答案
原则上你想要的没有错。但是,至少在 Coq 中,有一些简单的规则来检查模式匹配的类型,以便可以在类型中使用有关使用了哪个构造函数的信息。表面语言(在本例中为 Gallina)通过帮助编译(或 desugar)模式匹配来隐藏这种简单性,因此作为用户,您可以编写比底层系统必须处理的更复杂的模式。我对 Idris 不太熟悉,但根据依赖模式匹配的复杂程度,我怀疑您在那里遇到了类似的限制,您必须将代码放入系统可以进行类型检查的形式中。
在这里,您遇到了此模式匹配编译的两个限制。首先是构造函数的类型不是基于 s
上的匹配而专门化的。这很容易通过从 get_types s nat -> nat
计算一个函数来解决,编译器是正确的。
Require Import List.
Import ListNotations.
Inductive typ : Type := TB | TN.
Fixpoint get_types (s: list typ) (result_type: Type) : Type :=
match s with
| nil => result_type
| x :: xs => match x with
| TN => nat -> get_types xs result_type
| TB => bool -> get_types xs result_type
end
end.
Fail Fixpoint app (s: list typ) : get_types s nat -> nat :=
match s with
| nil => fun constructor => 2
| TB :: nil => fun constructor => constructor true
| TN :: nil => fun constructor => constructor 2
| TB :: xs => fun constructor => app xs (constructor true)
| TN :: xs => fun constructor => app xs (constructor 2)
end.
(* fails due to limitation of termination checker with nested matches *)
...但是您遇到了终止检查器的第二个问题。请注意,您的匹配很复杂:它分析 s
的结构以及它的头部和尾部(如果它是使用 cons
构建的)。最终,所有模式匹配都被编译为单个归纳类型上的嵌套模式匹配。如果你看这个展开,你正在将 s
分解为 t::xs
,然后再次将 xs
分解为 t0: :xs'
,最后在 xs
上递归。不幸的是,Coq 终止检查器仅将其视为 t0::xs'
并且不将其识别为 s
的子项(它真的想要 xs
)。
我很难以类型检查的方式手动编写您的函数,但这里有一个使用功能正确的策略编写的版本。请注意,它产生的定义比任何普通模式匹配都要复杂得多,因为它必须维护由 destruct_with_eqn
产生的证明。但是,该证明对于同时使用 xs
使终止检查器满意并揭示 t0::xs'
对构造函数的应用程序进行类型检查至关重要。它可能很复杂,但您仍然可以正常运行,如最后一行所示。
Fixpoint app (s: list typ) (constructor: get_types s nat) {struct s} : nat.
destruct s as [|t xs]; simpl in *.
exact 2.
destruct_with_eqn xs; simpl in *.
destruct t; [ exact (constructor true) | exact (constructor 2) ].
destruct t; simpl in *.
- apply (app xs).
subst.
exact (constructor true).
- apply (app xs).
subst.
exact (constructor 2).
Defined.
Eval compute in app [TB; TN] (fun x y => if x then y+2 else y).
(* = 4
: nat
*)
关于variadic-functions - 如何在 Coq 中使用有关此函数类型的已知信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48959586/
我试图创建一个模板,给定一组元函数和一个元函数,将这个元函数添加到提供的集合中。 template class...> class Dest, template c
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 7 年前。 Improve this qu
考虑以下代码 #define COMB(F, ...) F(__VA_ARGS__) #define ADD(X, Y) (X + Y) int foo() { return COMB(ADD
以下代码可以编译,因为我假设 parent的 Object本身没有 parent 。 template struct Object { T item; // T is item's typ
我目前正在研究一些新的 C++17 特性,特别是 std::optional,我决定尝试找到一个最小值使用可变参数模板的函数。这是我目前所拥有的: template typename Opt,
我想知道是我做错了什么还是编译器错误。我正在使用 Intel C++ Composer XE 2011 for Windows SP1(或更新 6,目前是最新的)。请参阅代码中的注释行。 #inclu
阅读可变参数函数时,我发现了一个 sum 函数,它接受任意数量的任意数字类型并计算它们的总和。 具有此函数的模板化特性,我希望它接受 string 对象,因为运算符 + 是为字符串定义的。 #incl
在 2012 ACCU C++ Pub quiz 的第 15 个问题中,我被结果难住了。 #include template void P(T x) { std::cout // foo 2 v
我在这里遗漏了一些关于类型推导的非常基本的东西: 我正在尝试编写一个包装函数,它调用一个带有 nullptr 的编写器函数以获得所需的长度,然后调整缓冲区大小,然后再次调用该函数,现在使用调整大小的缓
如何创建两个 VARIADIC 参数。查看我的代码并纠正我。 CREATE OR REPLACE FUNCTION ip_source_test(text,text,date,date,VARIADI
我希望创建一个类来检查两个参数类型列表,以查看是否可以将第一个列表中的所有参数转换为第二个列表。到目前为止,我有这样的事情: template class conv{ public: t
我想了解可变参数模板的工作原理。在下面的示例中,我想将变量参数传递给类的构造函数并将其存储到一个元组中,以供稍后使用。 template class CompoundOrs { public:
我正在尝试创建一个可变参数模板类,其方法需要迭代模板参数并为每种类型调用不相关的模板函数。 这个想法是用特定的模板参数扩展这个模板类,以封装基本行为。 一般想法的一个简单示例是这个(糟糕的)Check
考虑这个最小的例子: template struct foo {}; template class Bar> struct converter { template conv
我有以下测试程序: #include template struct Dispatcher { template static inline void call1(bool a, bool
我有一个模板化函数包装器,我正在尝试将其更新为 C++11 语法(可变参数)。 我的问题是我陷入了“第 22 条军规”,其中 'Args...' 必须是最后一个模板参数,但同时不能在函数指针之后定义模
我正在尝试组合一个通用方法调用程序(用于 C++ OO/v8 桥),使用可变参数模板元编程构建参数列表,转换为 native 类型,最后执行附加方法,一旦传入参数列表为空(因此构建了传出): temp
我已经使用可变参数函数来包装 printf(或 vprintf)。 除了在 warning_printf 的第一个可变参数上出错外,以下代码有效。此外,直接放置字符串会更改 ASCII 字符,但不会修
在 stackoverflow 问题之后:“具有零参数和逗号的可变参数宏”,我尝试了: #define MAKE_TEMPLATE(...) template MAKE_TEMPLATE() str
为了我的理解,我正在尝试使用可变参数模板编写一个简单的记录器。它有效,但有一个问题。 void log() { std::cout void log(T t1,
我是一名优秀的程序员,十分优秀!