本教程中的信息可能已经过时。请参见官方用户手册获取此页面上信息的最新版本。
本文件是从一个识字的Agda文件中提取的,该文件已使用Agda 2.3.0进行了测试。它使用标准库,应使用以下导入来检查此文件:
打开导入数据。布尔打开导入数据。国家打开导入数据。Vec隐藏(地图)打开导入数据。产品
目录
- 基础
- 如何声明记录类型
- 如何构造记录类型的值
- 如何分解记录类型的值
- 示例
- 显式记录构造函数
- 细节
- 记录上的模式匹配
- 细节
- 记录类型的转换规则
- 与“数据”声明的区别
- 递归记录
- “从属”记录
- 参数化记录类型
- 隐式字段
- 无关字段
- 只包含不相关字段的记录
- 一般语法和含义
- 打开记录以将字段纳入范围
- 记录打开示例
- 记录更新语法
- 使用附加功能扩展记录模块
- 更多示例
- 工具书类
- Agda中记录支持的变化历史:
基础
如何声明记录类型
记录类型可以将值组合在一起。它们的值是指定类型值的元组。例如,类型R(右)
在下面的代码片段中,引入了一个记录类型类型的值对布尔
和类型的ℕ
.
b:Bool——Bool类型的示例值b=假编号:ℕn=2——类型示例值ℕ记录R:设置位置领域f1:布尔f2:ℕ
f1级
和f2
是记录类型的“字段名”R(右)
.
如何构造记录类型的值
类型的值是什么R(右)
? 给定一个术语b条
类型为布尔
和n个
类型为ℕ
,记录{f1=b;f2=n}
是类型为的术语R(右)
,以及的所有值R(右)
以这种方式获得,在这种意义上R(右)
可转换为这种形式的条款。
因此,我们可能有一个声明,如
r:rr=记录{f1=b;f2=n}
请注意,分号(;)在这里是必需的。
如何分解记录类型的值
使用字段名,我们可以从类型的值中选择相应的组件R(右)
. 事实上,我们可能认为具有以下类型的两个函数被附加到上述类型的声明中R(右)
.
R.f1:R->布尔R.f2:R->ℕ
示例
假设我们想定义一个函数来增加R(右)
逐个记录。我们可以写:
增量InR:R->RincreaseInR r=记录{f1=r.f1 r;f2=suc(r.f2 r)}
显式记录构造函数
在Agda 2.2.6中,添加了对显式记录构造函数的支持。
我们可以编写R(右)
记录类型:
记录R2:设置位置构造函数r2——新增!领域f1:布尔f2:ℕ
请注意建造师
和领域
关键字必须缩进相同数量的空格。
的值R2级
现在可以通过两种方式创建:
--和以前一样注册会计师:R2rA=记录{f1=b;f2=n}--使用r2构造函数rB:R2rB=r2 bn
有可能微不足道地证明注册会计师
和英国皇家银行
可兑换:
--命题等式关系data_≡_{A:Set}:(ab:A)->设置位置参考:{a:a}→ a≡a记录等于:rA≡rBrecordsEqual=参考
细节
来自Agda 2.2.6发行说明:
可以定义记录构造函数:
记录∑(A:设置)(B:A→ Set):设置位置构造函数__领域项目₁ : A类项目二氧化碳:B项目₁
在本例中,_获取类型
(项目₁ : A)→ B项目₁ → ∑AB。
对于隐式字段,相应的构造函数参数变为隐含的。
请注意,构造函数是在外面的范围,所以任何固定性声明必须在记录定义之外给出。构造函数不在记录模块内的范围内。
记录上的模式匹配
在增加InR前面提到的示例中,模式匹配似乎很自然第页
但这是不允许的。然而,当记录类型已用构造函数声明时,模式匹配是可能的-请参见下文:
增量InR2:R2->R2增加InR2(r2 f1 f2)=r2 f1(例如f2)
细节
来自Agda 2.2.8发行说明:
现在可以对命名记录构造函数进行模式匹配。例子:
记录∑'(A:设置)(B:A→ Set):设置位置构造函数__领域项目₁ : A类项目₂ : B项目₁地图:{AB:Set}{P:A→ 集合}{Q:B→ 集合}(f:答→ B)→ (∀{x}→ 价格x→ Q(f x))→∑'A P→ ∑‘B Q映射fg(x,y)=(fx,gy)
上述条款在内部翻译为以下条款:
映射f g p=(f(∑'.proj₁ p) ,g(∑’项目₂ p) )
不转换包含数据类型模式的记录模式。例子:
添加:ℕ × ℕ → ℕ加(零,n)=n添加(suc m,n)=suc(添加(m,n))
注:在Agda 2.2.8和2.2.10中,记录不包含数据类型模式的模式,但其中包含点模式,被拒绝。Agda 2.3.0中对此进行了更改。以下示例现在有效:
Foo:{A:Set}(p₁ 第页₂ : A×A)→ 项目₁ 第页₁ ≡ 项目₁ 第页₂ → 设置₁Foo(x,y)(.x,y′)refl=设置
记录类型的转换规则
记录描述的字段投影在上面受以下方程式约束。对于任何条款答:r
:
R.f1 R≈bR.f2 R≈nr≈记录{f1=r.f1 r;f2=R.f2 R}
自R2级
定义了构造函数r2,对于任何项,我们也定义了r’:R2
r'≈r2(r2.f1 r')(r2.f2 r')
示例.
记录对:设置位置构造函数对领域fst(飞行时间):ℕ序列号:ℕextRec:(r:配对)→ r≡对(pair.fst r)(pair.snd r)extRec _=参考
为了证明extRec,我们甚至不需要对r-Agda皈依者对r(对r.fst r)(对r.snd r)
到第页
自动(可以使用交互式emacs模式查看)。
与“数据”声明的区别
我们可以用一个值定义一个类型,既可以作为记录,也可以使用“data”关键字。
录制TrueR:设置位置构造函数ttRdata TrueD:设置位置ttD:真
现在,让我们尝试证明“恰好一个值”引理:
始终正确:(t:TrueR)->t≡ttR始终正确=参考始终正确:(t:正确)->t选择ttDalwaysTrueD ttD=参考
在前一种情况下,我们不必进行模式匹配,但没有模式匹配,后一种情况就无法工作。
从实际的角度来看,这意味着您可以向Agda断言您返回的函数某种类型(比如一对)总是产生有人居住的价值。另一方面,如果单构造函数数据类型的索引为无法满足(例如,以refl和等式类型为例)。
参考:Daniel Peebles于2011年10月17日发布到邮件列表
递归记录
字段引用正在定义的类型的记录类型必须声明为感应的
或共同生产的
通过在记录定义中放置相关关键字,对齐以匹配建造师
和领域
关键字。否则将产生错误:
递归记录Foo需要声明为归纳或共归纳
“从属”记录
Agda有依赖类型。记录类型字段的类型可以取决于先前在记录类型声明中出现的相同记录类型的字段。例如,类型VecB公司
布尔值列表的参数化长度可以声明如下。
中缀5|_数据向量(X:集合):ℕ -> 设置位置[]:Vec X零_●_:{n:ℕ} -> X->Vec X n->Vec X(成功)VecB公司:ℕ -> 设置VecB=Vec Bool公司v:VecB n公司v=假|(真|[])——VecB n的示例值
VecB采用类型为的参数ℕ
并返回一个类型。然后,类型虚拟现实
一对自然数n个
和值VecB n公司
可以用以下方式声明。
记录VR:设置位置领域长度:ℕ向量:VecB长度
以下是虚拟现实
:
vr1:虚拟现实vr1=记录{长度=零;向量=[]}vr2:VR(虚拟现实)vr2=记录{长度=suc零;向量=trueб[]}虚拟现实:虚拟现实vr=记录{length=n;vector=v}
…和非示例:
记录{length=suck-zero;向量=[]}--向量场的类型是VecB(零),而不是VecB记录{length=suck-zero;向量=falseб(trueб[])}--矢量字段的类型是VecB(suc(suck-zero)),而不是VecB
这里是字段的类型矢量
取决于前一个字段的值,因为它的类型包含第一个字段的名称长度
.
依赖记录的选择器有点棘手,因为需要为字段名提供参数,以获取正确的目标类型。上述记录类型声明带来了以下两个功能:
VR.长度:VR->ℕVR.矢量:(VR:VR)->VecB(VR.长度VR)
与非依赖情况一样,我们具有以下可兑换性。
VR.长度VR≈nVR.矢量VR≈vv≈记录{长度=VR.长度VR;矢量=VR。矢量VR}
参数化记录类型
记录类型可能有参数。例如,我们可以声明一个带有类型参数的类型X(X)
并返回该长度的自然数和向量对的记录类型,其元素取自X(X)
,方法如下。
记录VRP(X:设置):设置位置领域伦恩:ℕvec:vec X透镜vrpNat:VRPℕvrpNat=记录{len=suc(suc零);vec=零(例如零)}
隐式字段
由于Agda 2.2.6记录字段可以隐性的:
记录RI:设置₁ where--包含集合中的字段,因此不能在集合本身中领域{B} :设置f:B->B{D F}E{G}:集合克:D->F->g
默认情况下,不打印隐式字段。
无关字段
你可以在无关性第章。
由于Agda 2.2.8记录字段可以变得无关。例子:
记录子集(A:集合)(P:A→ Set):设置位置建造师_#_领域元素:A证明:P元素
无关字段从不在范围内,也不在范围外记录。这意味着没有记录字段可以依赖于无关的字段。
在Agda 2.2.8中,没有为无关字段定义投影只能使用模式匹配进行访问。
由于Agda 2.2.10投影是为不相关的字段自动生成的(除非使用标记--no-irelevant-projections)。然而,请注意,无关的预测是高度实验性的。
只包含不相关字段的记录
自Agda 2.3.0以来,以下工程:
记录Is等价{A:Set}(_≈_:A→ A类→ Set):设置位置领域.ref:反射_≈_.sym:对称_≈_.trans:传递_≈_record Setoid:设置₁ 哪里中缀4≈_领域承运商:设置_≈_:载体→ 承运人→ 设置.is等效:isEquivalence_≈_打开IsEquivalence IsEquivalence公共
此前Agda对该应用程序提出投诉IsEquivalence就是Equivalent,因为isEquivality是不相关的,并且IsEquivalence模块需要相关参数。现在,什么时候记录模块是为只包含以下内容的记录生成的不相关的参数,记录参数变得不相关:
模Is等价{A:Set}{_≈_:A→ A类→ 集合}.(r:Is等价{A=A}_≈_)其中
一般语法和含义
记录类型通常按以下方式声明。
记录RΔ:设置为领域x个1:A1[年]1。。。,年m-1个]x个2:A2[年]1。。。,年m-1个,x个1]...x个n个:An个[年]1。。。,年m-1个,x个1…x个n-1个]
这里,Δ表示“望远镜”,其形式如下
(年)1:B1)(年)2:B2[年]1])。。。(年)米:B米[年]1…是的m-1个])
请注意B类2[年]1]
例如,并不意味着B类2
应用于年1
,但它的意思是B类2
变量可以自由出现年1
,但没有其他变量。有了这样的理解,人们可以简单地写下B类2
同样,A类n个[x1…x个n-1个]
在记录声明中仅表示术语A类n个
,如果它有任意变量的自由出现,则为x个1
...x个n-1个
.
此声明将以下标识符引入系统:
R:(年1:B1) -> ... -> (年米:B米)->设置钢筋混凝土1:{y1:B1} -> ... -> {年米:B米}->年1…是的米->A类1钢筋混凝土2:{y1:B1}->…->{年米:B米}->(r:Ry1…是的米)->A2[年]1。。。,年米、R.x1【参考文献】...钢筋混凝土n个:{y1:B1} -> ... -> {y米:B米}->(r:Ry1…是的米)->An个[年]1。。。,年米、R.x1r、 ,钢筋混凝土n个【参考文献】
R(右)
本身是参数化记录类型,并且钢筋混凝土1
, ...,钢筋混凝土n个
投影仪是R(右)
注意参数年1
, ...,年米
由于投影仪的值可以从第页
在许多情况下。
打开记录以将字段纳入范围
记录类型可能需要的两件事是适当命名的投影函数和打开一条记录以将字段带入范围。事实证明,使用模块化系统我们可以用一件的价格买到两件东西。对于上述记录R,我们生成一个参数化模块R(右)
模块R{Δ}(R:RΔ),其中x个1:A1[年]1。。。,年m-1个]x个1= ...x个2:A2[年]1。。。,年m-1个,x个1]x个2= ......x个n个:An个[年]1。。。,年m-1个,x个1…x个n-1个]x个n个= ...
中的函数R(右)
正是记录类型的投影函数R(右)
例如,我们有钢筋混凝土2:{Δ}(r:rΔ)->A2[右x1【参考文献】
(所以,用一些语言写的东西相对湿度2
对于答:r
,我们写为钢筋混凝土2第页
.)很明显,我们希望记录的参数为隐性的无论它们是否是记录的隐式参数。现在好消息是我们可以有效地将模块应用于给定的记录立即从记录中投影所有字段,这正是我们所做的在记录打开功能中查找。所以要打开一个记录r:r
我们只是说
打开R R
记录打开示例
假设我们有:
记录示例:设置位置字段布尔:布尔自然状态:ℕ例如:示例ex=记录{bool=true;nat=3}
我们想提取前
,但写作(例如)示例.池ex
可能会在短时间内感到疲劳。我们能做什么?
如果不打开示例模块,我们就没有任何选择:
--这在这里行不通-nat不在范围内--坏的:ℕ--坏=nat ex--正确的方法-完全合格的投影对的:ℕcorrect=示例.at ex
但是,我们可以打开为Example记录生成的Example模块得到更短的投影函数。如果我们不想污染整个顶层使用新名称的模块,我们可以在模块内打开它,也可以在单个声明中打开它(见下文)。
模块Open1,其中打开示例--我们有:--bool:(r':示例)→ 布尔--nat:(r’:示例)→ ℕ测试:ℕ测试=nat ex测试2:ℕtest2=nat ex where open示例
我们还可以打开给定记录值的Example模块,从而将其所有字段同时纳入范围:
模块Open2,其中打开示例ex--我们有:--bool≡true:bool--自然选择3:ℕ测试:ℕ测试=自然电位测试2’:ℕtest2'=nat,其中打开示例ex
记录更新语法
假设我们有一个记录类型和相应的值:
record MyRecord:设置位置领域x y z(x y z):ℕ旧:MyRecord旧=记录{x=1;y=2;z=3}
然后我们可以更新以下方式:
新建:MyRecordnew=记录旧{x=0;z=5}
在这里新的
归一化为记录{x=0;y=2;z=5}
.任何产生类型值的表达式我的记录
可以代替古老的
.
不允许更新记录以更改类型:结果值必须与原始类型相同,包括记录参数。因此,如果类型可以推断出原始记录的。
记录更新语法在类型检查之前展开。当表达
记录旧的{up-fields}
根据记录类型R进行检查,将其展开为
设r=记录{new-fields}中的旧字段,
其中旧的要求为R型,新的定义为如下:对于R中的每个字段x,
-如果x=e包含在upd-field中,则x=e包括在新油田等-如果x是显式字段,则x=R.x R包含在新油田,以及-如果x是隐式或实例字段,则从新油田。
(解释了实例参数在这里.)治疗原因隐式字段和实例字段特别允许以下代码:
记录R3:设置位置领域{长度}:ℕvec:车辆ℕ 长度--更多字段xs:R3型xs=记录{vec=0|1|2|[]}ys=记录xs{vec=0|[]}
如果没有特殊处理,最后一个表达式需要包含一个新的长度绑定(例如length=_)。
使用附加功能扩展记录模块
记录A:设置位置构造函数字段第1名:ℕ第2页:ℕ拭子A:AswapA=记录{n1=n2;n2=n1}--运行中的A记录类型答:答a=施工0 1a2:答a2=A交换A交换在--“定义范围”,这里有类型(r':A)→ A!
注意,当我们定义交换“虚拟选择器”时,我们无法访问构造函数施工
在两者上左侧和右侧。
更多示例
私人定义:
记录WithPriv(A:Set):设置位置私有的l:车辆ℕ (例如(例如零))l=零|(例如零|[])领域第一:A
提取隐式字段:
record Implicit:设置位置构造函数impl领域{k} :ℕ向量:向量ℕ k个获取:隐式->ℕget=隐式.kget2:隐式->ℕget2(impl{k}vec)=k
工具书类
Agda中记录支持的变化历史:
版本-2-2-6:
版本-2-2-8:
版本-2-10:
版本2-3-0:
- 添加了记录更新语法
- 只包含无关字段的记录的调整模块生成