(重定向自参考手册。带实例参数的建模类型类)
请参见官方用户手册获取此页面上信息的最新版本。
总有机碳
自2.3.0版以来,Agda提供了另一种类型的隐式函数参数:实例参数。实例参数的语法和语义在Agda 2.4.2中进行了更改,本手册仅描述了新版本。
实例参数的语法
实例参数的定义类似于隐式函数参数, 除非使用双花括号:
f:{{x:A}}→ B类
双花括号也可以替换为unicode符号⦃
和⦄
(在Emacs-Agda模式中键入“\{{”和“\}}”)。这需要在花括号前后加空格以引起Agda lexer注意它们不是标识符的一部分。
f:⦃x:A⦄→ B类
实例参数的语法类似于Agda的正常隐式论据。实例参数可以显式提供给函数,存在lambda表达式,可以使用对于所有人
语法等:
f⦃x⦄=。。。
λ⦃x:A⦄→ e;
对于所有⦃x⦄->。。。
如何解析实例参数
实例参数与普通隐式参数的区别在于重要方面。假设以下定义在范围内。
假设A B:集合
f:⦃x:A⦄→ B类
然后我们可以打电话(f)
没有参数的显式表达式x个
,阿格达会尽力推断。
测试:B
测试=f
然而,不仅仅是插入_
(类似于正常隐式参数),Agda将寻找候选表达式范围内。A类候选表达式是任何标识符(可能应用于隐藏参数),这是以下情况之一:
- 用特殊语句声明的标识符
实例
关键词;或 - 数据类型或记录的构造函数;或
- 局部变量(在局部
让
绑定或作为当前函数的参数)。
在类型检查期间,Agda检查是否只有一个此类标识符具有正确的类型并将其用作隐式参数不会立即使其他约束无效。如果是,此标识符被选中并用作缺少的参数。例如,如果我们
实例假设a:a
作为类型的唯一标识符一个
在范围内,则Agda将选择它作为调用缺少的标识符(f)
在定义中测试
以上。还考虑本地绑定的标识符:
测试:A→ B类
测试a=f
甚至
测试_=f
如果范围内有两个候选标识符:
实例假设a’:a
那么Agda将无法解决约束,并调用(f)
将在Emacs中用黄色标记。如果中没有有效的标识符范围,Agda将发出类型错误信号。
注:在Agda 2.4.2之前,没有实例
包含关键字和候选表达式全部的范围中的标识符。从Agda 2.4.3开始,即使数据类型构造函数也需要实例
关键字成为候选表达式。
递归示例
候选标识符本身可能依赖于更多实例参数,在这种情况下,它们将被递归解析。例如,考虑以下扩展任何集合的操作一个
通过再添加一个元素零
:
data Succ A:设置位置零:成功A成功:A->成功A
我们可以归纳定义一个子类型关系:
数据_<:_:设置->设置->设置₁ 哪里基:{A:Set}->A<:A步骤:{A B:集}->{p:A<:B}}->A<:成功B
这允许我们定义任何子类型到其超类型的规范嵌入:
转换:{AB:Set}->{p:A<:B}}->A->B强制转换{{base}}a=a转换{{step}}a=suc(转换a)
自从争论以来第页
到铸造
和步
是一个实例参数,Agda将尝试使用候选表达式自动解析它。例如:
plus3:{A:Set}->A->Succ(成功(成功A))plus3 x=铸造x
请注意,在解析实例参数时{{p}}
到铸造
运算符,Agda将考虑的唯一候选表达式是基础
和步
.(它们都是candiate表达式,因为它们是数据类型构造函数)。自步
它本身依赖于实例参数,它将被递归地解析。在上面的示例中,这是唯一成功的,结果项等价于
plus3x=cast{{step{{step{step}{base}}}}x
注意:在Agda 2.4.2之前,实例没有递归解析。
使用实例参数模拟Haskell类型类
实例参数可以用于不同的目的,但它们是也许作为Haskell类型类的替换最有用。一个典型的例子是哈斯克尔的等式
类型类别:
类Eq t,其中(==)::t->t->布尔
我们可以使用记录类型在Agda中对此进行建模:
record Eq(t:Set):设置,其中字段==:t→ t吨→ 布尔_/=_:t→ t吨→ 布尔a/=b=不是$a==b
我们现在可以打开一个包含_==_
和_/=_
函数采用等式
记录为实例参数:
打开等式{{…}}
这就引入了范围功能_==_
和_/=_
相当于以下内容:
_==_:{t:集合}→ {{eqT:等式}}→ t吨→ t吨→ 布尔_=={eqT}}=等式==_eqT_/=_:{t:集合}→ {{eqT:等式}}→ 吨→ t吨→ 布尔_/=_{{eqT}}=等式_/=_eqT
事实上,语法等同于以下内容(除了not定义名称包含隐式的等式
):
开放模块EqWithImplicits{t:Set}{eqT:eqT}}=EqeqT
现在,如果我们假设在作用域中有一些“类型类”的实例:
实例假设等式ℕ : 等式ℕeqBool:eqBool
然后我们可以使用_==_
和_/=_
自然数和布尔值就像他们的哈斯克尔等价物:
test=5==3∧真/=假
请注意等式
是一张普通的阿格达唱片。我们实际上可以与标准库中的任何记录相同:
打开导入关系。二进制使用(IsDecEquivalence;模块IsDeceEquivalce;模块DecSetoid)打开导入数据。Bool使用(false;true;decSetoid)使用(isDecEquivalence)打开DecSetoid打开模块IsDecEquivalenceWithImplicits{aℓ} {A:设置A}{_≈_:A→ A类→ 设置ℓ} {{ide:IsDecEquivalence_≈_}}=IsDecEquivalence ide测试=假≟真
请注意测试:false≡true
是部分由值定义isDec等效
为调用的实例参数_≟_
。如果isDec等效
在范围内,测试
可能会有不同的值和其他类型。