假设您要定义一系列二元运算符(由集合索引,例如),其中参数的类型取决于索引的值,并且显式传递索引。此外,假设您希望该系列的成员可以使用中缀表示法:
x <[A] y
这是索引;括号[ - ]应该表示A应该被读作下标。为这种与此语法兼容的操作提供类型签名很困难,因为x的类型取决于值 A,因此A : Set
必须出现在x : A
的左侧在_<[_]_
。
我基于syntax
声明尝试了以下技巧(黑客?):
cmp : (A : Set) → A → A → Set
cmp = {!!}
syntax cmp A x y = x <[ A ] y
postulate C : Set
postulate c : C
x = c <[ C ] c
除非您的二进制操作使用隐式实例,否则这似乎有效。如果我尝试将{{x}}
形式的参数添加到syntax
声明,Agda会抱怨。 (也许并非不合理。)
似乎可以通过引入cmp
的版本来明确地采用隐式实例,然后定义调用该版本的语法变体:
postulate B : Set
-- Now expects an ambient B.
cmp : (A : Set) {{b : B}} → A → A → Set
cmp = {!!}
-- Version of cmp that makes implicit instance explicit.
cmp-explicit : (A : Set) (b : B) → A → A → Set
cmp-explicit A b = cmp A {{b}}
syntax cmp A x y = x <[ A ] y
syntax cmp-explicit A b x y = x <[ A at b ] y
postulate C : Set
postulate c : C
postulate b : B
x = c <[ C ] c -- pick up ambient B
y = c <[ C at b ] c -- pass B explicitly
(由于syntax
似乎不支持{{x}}
参数,因此无法将cmp
内联到cmp-explicit
,而不会放弃获取环境B的能力完全。)
这是一个黑客吗?当y的类型取决于x的值,并且显式传递x时,是否有另一种方法来翻转参数x和y?
当然,定义
_<′[_]_ = λ x A y → cmp A x y
导致Agda在类型检查x
时抱怨。
答案 0 :(得分:2)
你不能真正以A : Set
x : A
之后syntax
的方式翻转参数。
您已经提到x <[ A ] y
,我认为这是最佳解决方案。这是有效的,因为Agda会将cmp A x y
转换为_<[_]_ : {A : Set} → A → ? → A → Set
,对于类型检查器来说这很好。
这是另一种(相当丑陋和黑客)的方法。假设我们有:
A
在这里我们可以稍微利用统一:通过在?
洞中使用提及A
的内容,我们可以强制类型检查器填充前面的隐式?
。但据我所知,我们不能使用简单的类型代替x <[ A ] y
,因此我们得到了所需的data Is : Set → Set₁ where
is : (A : Set) → Is A
_<[_]_ : {A : Set} → A → Is A → A → Set
x <[ is A ] y = cmp A x y
。但要完成这个想法,这里有一件事是有效的:
syntax
是的,这是相当丑陋的,我建议不要这样做。
但回到关于syntax
的问题:我不会认为syntax
是任何方式的黑客攻击。事实上,标准库在一个地方使用Data.Plus
的方式大致相同(确切地说syntax Plus R x y = x [ R ]⁺ y
):
cmp-explicit
即使cmp-syntax = cmp
cmp-explicit-syntax = λ A b → cmp A {{b}}
syntax cmp-syntax A x y = x <[ A ] y
syntax cmp-explicit-syntax A b x y = x <[ A at b ] y
周围也很有用。我甚至会建议你再制作两个版本:
_<[_]_
如果模块的用户不想使用语法快捷方式(例如,他导入另一个定义cmp
的模块),他只需选择不导入它,但仍然有Σ
周围。
同样,标准库使用open import Data.Nat
open import Data.Product
open import Relation.Binary.PropositionalEquality
x : Σ[ n ∈ ℕ ] n + 2 ≡ 4
x = 2 , refl
的语法快捷方式执行此操作。快捷方式允许您编写:
open import Data.Product
hiding (Σ-syntax)
如果您不想要它,那么您只需:
{{1}}