给定以下数据类型,该数据类型对两个自然数之间经过验证的比较进行编码:
open import Agda.Builtin.Nat
data Compare : Nat -> Nat -> Set where
LT : {m : Nat} {n : Nat} -> Compare m (suc (m + n))
EQ : {m : Nat} -> Compare m m
GT : {m : Nat} {n : Nat} -> Compare (suc (m + n)) m
以下代码正确地比较数字并计算其差异:
comparehelper : {m : Nat} {n : Nat} -> (Compare m n) -> Compare (suc m) (suc n)
comparehelper LT = LT
comparehelper EQ = EQ
comparehelper GT = GT
compare : (m : Nat) (n : Nat) -> Compare m n
compare 0 0 = EQ
compare (suc _) 0 = GT
compare 0 (suc _) = LT
compare (suc m) (suc n) = comparehelper (compare m n)
differencehelper : {m : Nat} {n : Nat} -> (Compare m n) -> Nat
differencehelper (LT {n = difflt1}) = suc difflt1
differencehelper EQ = 0
differencehelper (GT {n = difflt1}) = suc difflt1
difference : Nat -> Nat -> Nat
difference m n = differencehelper (compare m n)
但是下面的,显然功能相同的代码没有( 模式匹配失败类型检查):
compare' : (m : Nat) (n : Nat) -> Compare m n
compare' 0 0 = EQ
compare' (suc _) 0 = GT
compare' 0 (suc _) = LT
compare' (suc m) (suc n) with compare' m n
... | LT = LT
... | EQ = EQ
... | GT = GT
difference' : Nat -> Nat -> Nat
difference' m n with compare' m n
... | LT {n = difflt1} = suc difflt1
... | EQ = 0
... | GT {n = difflt1} = suc difflt1
对行为差异的解释是什么?如问题中所述,我正在运行Agda 2.5.1.2。
答案 0 :(得分:3)
此处的问题是,Compare m n
类型值的模式匹配会优化m
和n
的模式。
因此compare' (suc m) (suc n)
所代表的方案...
不再有效。你必须用精致的图案重复左手边,例如
compare' (suc m) (suc n) with compare' m n
compare' (suc m) (suc .(suc m + _)) | LT = LT
compare' (suc m) (suc .m) | EQ = EQ
compare' (suc .(suc m + _)) (suc m) | GT = GT
我在这里使用了下划线来表示范围内但未明确命名的变量(它们分别是LT
和GT
的隐式参数)。它们未被命名但在模式中需要的事实可能是一个很好的线索,它们应该是LT
和GT
构造函数的明确参数。
或者,如果您不关心模式,可以使用下划线(可以代表任何模式,包括虚线模式)并写入:
compare' (suc _) (suc _) | LT = LT
compare' (suc _) (suc _) | EQ = EQ
compare' (suc _) (suc _) | GT = GT
正如@asr所说,较新版本的Agda将支持您当前的模式匹配,因为dot patterns have been made optional。