后继者的 Idris 模式匹配(下一个值)

Idris pattern matching on successor (next value)

在以下函数中,我在 (S k) 上对 k 的后继进行模式匹配

vectTake : (n : Nat) -> Vect (n + m) a -> Vect n a
vectTake Z xs = []
vectTake (S k) (x :: xs) = x :: vectTake k xs

是否可以根据需要在函数体中使用该值?

另一种解决方案是在 k 上进行匹配,并在主体函数上使用 k 的先行项,以便解决相同问题的另一种形式或这种模式匹配提供我看不到的任何其他优势?

关于你的第一个问题...

Nat 的(原始)定义是

data Nat = Z | S Nat

我们可以匹配:

  • 使用k
  • 的任意值
  • 构造函数。这是 ZS k 。当然 S k 会将不同的值绑定到 k ,而不是我们仅在 k
  • 上进行模式匹配

一旦你匹配了一个值,你就可以做所有你通常可以用 Nat 做的事情,包括使用 S 构造后继者,所以如果你想匹配 S k 并在函数中使用它,你可以

...
vectTake (S k) (x :: xs) = (S k) :: vectTake k xs

虽然在这里我改变了你函数的含义来说明我的观点。在此示例中,您还可以使用 命名模式

...
vectTake count@(S k) (x :: xs) = count :: vectTake k xs

关于你的第二个问题...

pred k 我假设你的意思是前驱而不是谓词。如果是这样,你可以对Nat包括k - 1进行整数运算,所以,回到vecTake

的原始定义
...
vectTake k (x :: xs) = x :: vectTake (k - 1) xs

请注意,这取决于首先匹配 Z,否则您最终将执行无法编译的 Z - 1

至于 ZS kZk 匹配哪个更好,我想不出 objective一个人比另一个人更好的原因。也许在某些情况下会影响性能,但我无法在这方面为您提供帮助。我主要使用构造函数模式,因为人们会习惯于看到它,但我确信在某些情况下其他样式是必要的。