cong怎么可以打字好?

Mai*_*tor 0 agda

我在看下面的定义cong:

cong : ? {a b} {A : Set a} {B : Set b} (f : A ? B) {x y} ? x ? y ? f x ? f y
cong f refl = refl
Run Code Online (Sandbox Code Playgroud)

我无法理解为什么它的打字很好.特别是,似乎隐含的论点refl必须是f xf y.为了使事情更清楚,我写了一个非隐式的相等版本,并试图复制证明:

data Eq : (A : Set) -> A -> A -> Set where
  refl : (A : Set) -> (x : A) -> Eq A x x

cong : (A : Set) -> (B : Set) -> (f : A -> B) -> 
       (x : A) -> (y : A) -> (e : Eq A x y) -> Eq B (f x) (f y)
cong A B f x y e = refl B (f x)
Run Code Online (Sandbox Code Playgroud)

这会导致类型错误:

x != y of type A when checking that the expression refl B (f x) has type Eq B (f x) (f y)
Run Code Online (Sandbox Code Playgroud)

正如人们所料.我可能有什么而不​​是(f x)?我错过了什么吗?

use*_*465 5

您服务的相关模式匹配.

如果我们在你的洞里打个洞 cong

cong : (A : Set) -> (B : Set) -> (f : A -> B) ->
       (x : A) -> (y : A) -> (e : Eq A x y) -> Eq B (f x) (f y)
cong A B f x y e = {!refl B (f x)!}
Run Code Online (Sandbox Code Playgroud)

我们会看到它

Goal: Eq B (f x) (f y)
Have: Eq B (f x) (f x)
Run Code Online (Sandbox Code Playgroud)

所以价值确实不同.但是一旦你模式匹配e:

cong : (A : Set) -> (B : Set) -> (f : A -> B) ->
       (x : A) -> (y : A) -> (e : Eq A x y) -> Eq B (f x) (f y)
cong A B f x y (refl .A .x) = {!refl B (f x)!}
Run Code Online (Sandbox Code Playgroud)

这个事实xy所揭示的相同,并且上下文被默默地重写:每次出现都y被替换为x,所以看看我们现在看到的洞

Goal: Eq B (f x) (f x)
Have: Eq B (f x) (f x)
Run Code Online (Sandbox Code Playgroud)

请注意,我们可以写

cong A B f x .x (refl .A .x) = refl B (f x)
Run Code Online (Sandbox Code Playgroud)

即不要完全绑定y,只是说它与x通过点模式相同.我们通过模式匹配获得了这些信息e : Eq A x y,因为一旦完成匹配,我们就知道它e : Eq A x x实际上是因为这就是所说的类型签名refl.统一Eq A x yEq A x x产生一个微不足道的结论:y平等x和整个背景相应调整.

这与Haskell GADT的逻辑相同:

data Value a where
  ValueInt  :: Int  -> Value Int
  ValueBool :: Bool -> Value Bool

eval :: Value a -> a
eval (ValueInt  i) = i
eval (ValueBool b) = b
Run Code Online (Sandbox Code Playgroud)

当你匹配ValueInt并得到i类型时Int,你也会揭示出a等于Int并将这些知识添加到上下文中(通过一个等式约束),这在以后会产生a并且是Int统一的.这就是我们能够返回i的结果:因为a从类型签名和Int完全统一,正如我们从上下文中知道的那样.