在最简单的情况下具有
构造只能用于区分中间计算的结果。例如
滤波器 : {A类: 设置} → (A类→布尔) →列表A→列表A过滤器p[]=[]滤波器p(x|x) 具有第x页过滤器p(x|x) |真实的=x滤波器pxs滤波器p(x|x) |假=过滤器pxs
包含with-abstraction的子句没有右手边。相反,它后面是一些子句,左边有一个额外的参数,用竖线与原始参数分开(|
).
当新子句中的原始参数相同时,可以使用...
语法:
滤波器 : {A类: 设置} → (A类→布尔) →列表A→列表A过滤器p[]=[]过滤器p(x|x) 具有第x页... |真实的=x滤波器pxs... |假=过滤器pxs
在这种情况下...
扩展到滤波器 第页 (x) ∷ X轴)
。有三种情况在这里你必须拼写出左手边:
- 如果您想对原始参数进行进一步的模式匹配。
- 当对中间结果进行模式匹配时其他参数(请参见点状图案).
- 要消除与抽象嵌套的子句之间的歧义(请参见用抽象嵌套(见下文)。
带抽象的力量来自这样一个事实:目标类型和原始参数的类型被概括为scrutine的值。请参见技术细节详情请参见下文。这种概括是当您必须证明使用定义的函数的属性时很重要具有
例如,假设我们想证明滤波器
功能以上满足某些性质对
。从的模式匹配开始列出我们得到的以下内容(孔中显示了目标类型)
假设对: ∀ {A类} →列表A→ 设置
假设p-无:P【】假设问: 设置
假设q-nil(q-nil):问
证明 : {A类: 设置} (第页:A类→布尔) (X轴:列表A) →对(滤波器p xs)证明p[]= {!P[]!}证明p(x|x) = {!P(筛选器pxs|px)!}
在犯罪案件中,我们必须证明对
等待滤波器 第页 X轴 | 第页 x个
.这是一个卡住了的抽象的语法-滤波器
无法减少因为我们不知道第页 x个
。此语法用于打印,但不接受为有效的Agda代码。现在如果我们在抽象结束第页 x个
,但是不匹配我们得到的结果:
证明 : {A类: 设置} (第页:A类→布尔) (X轴:列表A) →对(过滤器pxs)证明p[]=p-无证明p(x|x) 具有第x页... |第页= {!P(筛选器pxs|r)!}
这里是第页 x个
目标类型中的已被变量替换第页
为的结果而引入第页 x个
.如果我们模式匹配第页
这个with-clauses可以减少,给我们:
证明 : {A类: 设置} (第页:A类→布尔) (X轴:列表A) →对(过滤器pxs)证明p[]=p-无证明p(x|x) 具有第x页... |真实的= {!P(xŞfilter P xs)!}
... |假= {!P(过滤器pxs)!}
目标类型和其他参数的类型都是泛化的,所以如果参数的类型包含滤波器 第页 X轴
.
证明₂ : {A类: 设置} (第页:A类→布尔) (X轴:列表A) →对(过滤器pxs) →问证明₂ 第[]页_=q为零证明₂ 第页(x|x)H(H)具有第x页... |真实的= {!H:P(过滤器pxs)!}
... |假= {!H:P(x过滤器pxs)!}
概括并不局限于其他带有抽象的细节。全部目标类型和参数类型中出现的术语将为概括。
请注意,这种概括并不总是类型正确的,可能会导致(有时是隐秘的)类型错误。请参见带摘要的类型错误以下为更多详细信息。
With-abstractions可以任意嵌套。唯一要记住的事这个案例是...
语法适用于最接近的with-abstraction。例如,假设您想使用...
在下面的定义中。
比较 :国家→国家→比较比较x y具有x<y比较x y|假具有y<x比较x y|假|假=平等的比较x y|假|真实的=更大的比较x y|真实的=较少的
你可能会想替换比较 x个 年
具有...
在所有的用如下条款。
比较 :国家→国家→比较比较x y具有x<y... |假具有y<x... |假=平等的... |真实的=更大的... |真实的=较少的--错误
然而,这是错误的。在最后一句中...
被解释为属于带抽象的内部(空白不被纳入账户),从而扩展到比较 x个 年 | 假 | 真实的
.在这种情况下,您必须拼写出左手边并写
比较 :国家→国家→比较比较x y具有x<y... |假具有y<x... |假=平等的... |真实的=更大的比较x y|真实的=较少的
您可以使用抽象在单个术语中对多个术语进行抽象。要做到这一点你用竖线分隔术语(|
).
比较 :国家→国家→比较比较x y具有x<y|y<x... |真实的|_=较少的... |_|真实的=更大的... |假|假=平等的
在本例中,抽象术语的顺序无关紧要,但一般而言确实如此。具体地说,后面的术语类型在值上进行了概括早期条款。例如
假设加号-调号: (a b类:国家) →a+b≡b+a假设对:国家→ 设置
三分之一 : (a b类:国家) →对(a+b) →对(b+a)thma b t公司具有a+b|加减a bthma b t公司|ab公司|等式= {!t:P ab,eq:ab≡b+a!}
请注意吨
以及结果的类型等式
属于加号-调号 一 b条
已被概括一 + b条
。如果随着抽象被翻转,情况就不一样了。如果我们现在模式匹配打开等式
我们得到
三分之一 : (a b类:国家) →对(a+b) →对(b+a)thma b t公司具有a+b|加号-调号a bthma b t公司| .(b+a) |回流= {!t:P(b+a)!}
从而可以用吨
实际上,我们使用了交换性重写证明一 + b条
到b条 + 一
类型为吨
。这真是一个这样做很有用,因为它有特殊的语法。请参阅重写如下所示。
泛化的一个限制是,只有出现以下术语抽象时可见的被概括,但更多的实例一旦你开始填写右侧或在左侧进一步匹配。例如,考虑以下人为的我们需要匹配(f) n个
对于类型q个
到减少,但我们想申请q个
到一个引理(f) n个
:
假设
R(右) : 设置
对 :国家→ 设置
(f) :国家→国家引理 : ∀n个→对(f个n) →R(右)问 :国家→ 设置Q零=Ş问(例如) =对(例如)
证明 : (n个:国家) →问(f个n) →R(右)证明n q具有f个n证明n() |零证明n q|例如fn= {!q:P(例如fn)!}
一旦我们概括过来(f) n个
我们不能再应用引理,它需要类型为的参数对 (f) n)
。为了解决此问题,我们可以添加抽象的引理:
证明 : (n个:国家) →问(f个n) →R(右)证明n q具有f个n|引理n证明n() |零|_证明n q|例如fn|莱姆=勒姆q
在这种情况下引理 n个
(对 (f) n) → R(右)
)被概括为(f)
n个
所以在最后一条的右边我们有q个 : 对 (例如 fn)
和莱姆 : 对 (成功 fn) → R(右)
.
请参见Inspect习语下面介绍了一种替代方法。
记住以下示例同时提取从上面。
假设加号-调号: (a b类:国家) →a+b≡b+a三分之一 : (a b类:国家) →对(a+b) →对(b+a)thma b t公司具有a+b|加减a bthma b t公司| .(b+a) |回流=吨
通过在方程式及其上进行抽象来重写方程式的这种模式左手边很常见,因此有特殊的语法:
三分之一 : (a b类:国家) →对(a+b) →对(b+a)thma b t公司重写加号-调号a b=吨
这个重写
建造需要一个学期等式
类型为左侧(lhs) ≡ 相对湿度
,其中_≡_
是内置相等类型,并扩展为带有以下内容的摘要左侧(lhs)
和等式
然后是匹配的结果等式
反对回流
:
英尺/秒重写等式=v(v)-->英尺/秒具有左侧(lhs)|等式... | .相对湿度|回流=v(v)
一个限制重写
结构就是你不能再做了参数的模式匹配之后重写,因为一切都发生了在一个子句中。然而,在重写之后,您可以使用抽象。对于实例,
假设T型:国家→ 设置
是偶数 :国家→布尔等于零=真实的是偶数(真空零点) =假是偶数(苏克(例如)) =是偶数n三分之一¦Β : (a b类:国家) →T型(a+b) →T型(b+a)三分之一₁ a b t公司重写加号-调号a b具有甚至是一个三分之一₁ a b t公司|真实的=吨三分之一₁ a b t公司|假=吨
请注意,重写引入的with-abstracted参数(左侧(lhs)
和等式
)在代码中不可见。
当你用抽象词吨
你失去了吨
和表示其值的新参数。只要所有实例都可以属于吨
您关心通过抽象进行概括,但正如我们所看到的在上面情况并非总是如此。在这个例子中,我们使用了同时抽象,以确保我们确实捕获了我们的所有实例需要。另一种方法是使用检查习语,它保留了证明原始术语等于其抽象的证据。
在最简单的形式中,inspect习惯用法使用单例类型:
数据辛格尔顿{一} {A类: 设置一} (x个:A类) : 设置一哪里
_带有≡_ : (年:A类) →x≡y→单例x检查 : ∀ {一} {A类: 设置一} (x个:A类) →单例x检查x=x个具有≡ref
现在不用抽象了吨
,您可以抽象检查 吨
。对于实例,
滤波器 : {A类: 设置} → (A类→布尔) →列表A→列表A过滤器p[]=[]过滤器p(x|x) 具有检查(第x页)
... |真实的具有选择当量= {!eq:px≡true!}
... |假具有≡eq= {!eq:px≡false!}
这是我们得到的证据第页 x个 ≡ 真实的
和第页 x个 ≡ 假
在各自的我们可以使用正确的分支。注意,由于with-abstraction是结束检查 (第页 x)
而不是第页 x个
,目标和参数类型为否更长的概括第页 x个
。要修复此问题,我们可以替换单例类型按如下功能图类型(参见匿名模块学习关于使用模块将类型参数绑定到图表
和检查
):
模块_ {一b条} {A类: 设置一} {B类:A类→ 设置b条} 哪里
数据图表((f): ∀x个→B个x) (x个:A类) (年:B个x) : 设置b条哪里
内窥镜 :f x≡y→图f x y检查 : ((f): ∀x个→B个x) (x个:A类) →图f x(f x(f x))检查__=内窥镜反射
将其用于术语克 v(v)
你对这两件事都很抽象克 v(v)
和检查
克 v(v)
例如,将此应用到上面的示例中,我们得到
假设
R(右) : 设置
对 :国家→ 设置
(f) :国家→国家引理 : ∀n个→对(f个n) →R(右)问 :国家→ 设置Q零=Ş问(例如) =对(例如)
证明 : (n个:国家) →问(f个n) →R(右)证明nq具有f个n|检查f n证明n() |零|_证明n q|例如fn|英格拉夫当量= {!q:P(suc-fn),eq:f n≡suc-fm!}
然后我们可以用证据证明(f) n个 ≡ 苏克 fn公司
申请引理
到q个
.
这个版本的inspect习语是定义的(使用稍微不同的名称)在中标准库在模块中关系。二元的。命题等式
和在agda-prelude公司在里面前奏曲。平等。检查
(由重新出口前奏曲
).
虽然带抽象非常强大,但在某些情况下,您无法或不想使用它。例如,如果您是在右侧的表达式中。在这种情况下,有几个选择。
lambdas图案
Agda没有原语案例
构造,但可以模拟一个使用模式匹配lambdas。首先定义功能案例(共个)_
如下:
案例(_O)_ : ∀ {a b类} {A类: 设置一} {B类: 设置b条} →A类→ (A类→B类) →B类f的情况x=f x(f x)
然后,您可以将此函数与模式匹配的lambda用作第二个获取Haskell样式case表达式的参数:
滤波器 : {A类: 设置} → (A类→布尔) →列表A→列表A过滤器p[]=[]过滤器p(x|x) =案例p x,共个λ{真实的→x滤波器pxs; 假→过滤器pxs}
此版本的案例(_O)_
仅适用于非依赖函数。对于依赖函数-目标类型在大多数情况下是不可推断的,但是可以将变量与显式B类
对于这种情况:
案例返回_ : ∀ {a b类} {A类: 设置一} (x个:A类) (B类:A类→ 设置b条) → (∀x个→B个x) →B个xcase x返回B of f=f x(f x)
依赖版本将允许您对scrutine进行概括,就像使用抽象,但必须手动执行。它不允许你做的两件事是
- 左侧参数的进一步模式匹配,以及
- 通过case表达式中的模式细化左侧的参数。对于实例,如果您匹配
Vec公司 A类 n个
这个n个
将由零和缺点模式。
助手函数
内部with-abstractions转换为辅助函数(请参见技术细节下面),您可以随时写下这些手动运行。缺点是helper的类型签名函数需要显式写出,但幸运的是Emacs模式有一个命令(抄送 C-小时
)使用相同的生成with-function类型的算法。
内部with-abstractions被转换为辅助函数–有中没有带摘要的核心语言。此翻译进行如下如下。给出带抽象的
哪里(即。键入绑定的变量),我们
下面是一些with-abstractions及其翻译的示例。
假设
A类 : 设置
_+_ :A类→A类→A类T型 :A类→ 设置
mkT公司 : ∀x个→T x(T x)对 : ∀x个→T x(T x)→ 设置
--with参数的类型A没有自由变量,因此with
--首先是争论
(f)¦Β : (x年:A类) (吨:T型(x+y)) →T型(x+y)(f)₁ x年t具有x+y(f)₁ x年t|w个= {!!}
--使用函数生成
f辅助¦Β : (w个:A类) (x年:A类) (吨:T重量) →T重量f辅助₁ 宽x厚= {!!}
--输入with参数不需要x和p,因此上下文
--在with参数之前仅用y重新排序
(f)₂ : (x年:A类) (第页:同比(mkT年)) →同比(mkT年)(f)₂ x y p(x y p)具有mkT年(f)₂ x y p(x y p)|w个= {!!}
f辅助₂ : (年:A类) (w个:年) (x个:A类) (第页:同比) →同比f辅助₂ y宽x p= {!!}
假设
H(H) : ∀x年→T型(x+y) → 设置
--带参数的多个始终插入在一起,因此在本例中
--t最后出现在左边,因为需要输入h,因此x+y不是
--从t型中抽象出来
(f)₃ : (x年:A类) (吨:T型(x+y)) (小时:高x厚) →T型(x+y)(f)₃ x年t小时具有x+y|小时(f)₃ x年t小时|w个¦Β|w个₂= {!t:t(x+y),目标:t w₁ !}
f辅助₃ : (x年:A类) (吨:T型(x+y)) (小时:高x厚) (w个¦Β:A类) (w个₂:高x厚) →T重量¦Βf辅助₃ x y t h w₁ w个₂= {!!}
--但前面的带参数是从后面的类型中抽象出来的
(f)₄ : (x年:A类) (吨:T型(x+y)) →T型(x+y)(f)₄ x年t具有x+y|吨(f)₄ x年t|w个¦Β|w个₂= {!t:t(x+y),w₂ : T重量₁, 目标:T w₁ !}
f辅助₄ : (x年:A类) (吨:T型(x+y)) (w个¦Β:A类) (w个₂:T重量¦Β) →T重量¦Βf辅助₄ x年t月₁ w个₂= {!!}
如上所述,泛化并不总是产生类型良好的结果。当您对出现在类型子团队的目标或参数类型的。最简单的示例是对相关对的第一个分量。例如,
假设
A类 : 设置
B类 :A类→ 设置
H(H) : (x个:A类) →B个x→ 设置
坏的,坏的 : (第页:∑A B) →H(H)(fst压力) (信噪比)带p的坏具有fst压力... |_= {!!}
这里,概括一下有限状态试验 第页
生成ill类型的应用程序H(H) w个
(瑞士) 第页)
您将得到以下类型错误:
fst p!=A型w当检查类型(p:∑A B)(w:A)→ H w(snd p),共用函数生成的格式良好
此消息可能有点难以解释,因为它只打印眼前的问题(有限状态试验 第页 != w个
)和功能齐全。收件人获取更详细的错误,指向类型中错误是,您可以从错误消息中复制并粘贴with-function类型并尝试单独键入检查。