Agda 2.5.1.2中模式匹配失败

时间:2016-12-12 01:25:24

标签: pattern-matching agda

给定以下数据类型,该数据类型对两个自然数之间经过验证的比较进行编码:

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。

1 个答案:

答案 0 :(得分:3)

此处的问题是,Compare m n类型值的模式匹配会优化mn的模式。

因此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

我在这里使用了下划线来表示范围内但未明确命名的变量(它们分别是LTGT的隐式参数)。它们未被命名但在模式中需要的事实可能是一个很好的线索,它们应该是LTGT构造函数的明确参数。

或者,如果您不关心模式,可以使用下划线(可以代表任何模式,包括虚线模式)并写入:

compare' (suc _) (suc _) | LT = LT
compare' (suc _) (suc _) | EQ = EQ
compare' (suc _) (suc _) | GT = GT

正如@asr所说,较新版本的Agda将支持您当前的模式匹配,因为dot patterns have been made optional