我正在使用Idris进行第8章类型驱动开发,我有一个关于重写如何与Refl交互的问题。
此代码显示为重写如何对表达式起作用的示例:
myReverse : Vect n elem -> Vect n elem
myReverse [] = []
myReverse {n = S k} (x :: xs)
= let result = myReverse xs ++ [x] in
rewrite plusCommutative 1 k in result
其中plusCommutative 1 k
将查找1 + k
的任何实例,并将其替换为k + 1
。
我的问题是这个解决方案将plusCommutative
作为myPlusCommutes
的一部分进行重写,答案是:
myPlusCommutes : (n : Nat) -> (m : Nat) -> n + m = m + n
myPlusCommutes Z m = rewrite plusZeroRightNeutral m in Refl
myPlusCommutes (S k) m = rewrite myPlusCommutes k m in
rewrite plusSuccRightSucc m k in Refl
我遇到这条线路有问题:
myPlusCommutes Z m = rewrite plusZeroRightNeutral m in Refl
因为我可以通过在该行中单独使用Refl来理解:
myPlusCommutes Z m = Refl
我收到此错误:
When checking right hand side of myPlusCommutes with expected type
0 + m = m + 0
Type mismatch between
plus m 0 = plus m 0 (Type of Refl)
and
m = plus m 0 (Expected type)
Specifically:
Type mismatch between
plus m 0
and
m
首先,我没有意识到的一件事是,似乎Refl在=
的右侧起作用并寻求从那个方向反射。
接下来,似乎重写Refl会导致从plus m 0 = plus m 0
更改为m = plus m 0
,从左侧重写但在第一次替换后停止,并且不会更换所有实例正如我所期望的那样plus m 0
m
。
最终,这是我的问题,为什么重写会以这种方式表现。重写相等类型是不同的,在这些情况下,重写仅替换=
的左侧?
答案 0 :(得分:2)
为了理解这里发生了什么,我们需要考虑Refl
是多态的这一事实:
λΠ> :set showimplicits
λΠ> :t Refl
Refl : {A : Type} -> {x : A} -> (=) {A = A} {B = A} x x
这意味着Idris正试图使用来自上下文的信息将类型归因于术语Refl
。例如。 Refl
中的myPlusCommutes Z m = Refl
类型为plus m 0 = plus m 0
。 Idris本可以选择myPlusCommutes
'输出类型的LHS,并尝试将类型m = m
归因于Refl
。您也可以像x
一样指定Refl {x = m}
表达式。
现在,rewrite
适用于您的当前目标,即rewrite Eq
将Eq
的LHS的所有出现替换为其< em>目标,而不是Refl
的某些可能类型。
让我举一个使用一系列重写来说明我的意思的愚蠢的例子:
foo : (n : Nat) -> n = (n + Z) + Z
foo n =
rewrite sym $ plusAssociative n Z Z in -- 1
rewrite plusZeroRightNeutral n in -- 2
Refl -- 3
n = (n + Z) + Z
开始,然后是n = n + (Z + Z)
,然后n = n + Z
(定义上等于n = n + (Z + Z)
)转换为n = n
Refl {x = n}
代替Refl
)。