证明索引在列表范围内(索引+ 1)在范围内

时间:2018-02-26 19:36:58

标签: idris

假设我们有一个list : List a,我们想要使用它的第一个和第二个元素:

case inBounds 1 list of
     Yes prf => doSmth (index 0 list) (index 1 list)
     No _ => doSmthElse

不幸的是,这不是类型检查:事实上,prfInBounds 1 list所持有的证明,但是对于我们人类来说,InBounds 0 list紧随其后,它仍然需要显示对于typechecker。

当然,有人可能会写一份帮助证明

inBoundsDecr : InBounds (S k) xs -> InBounds k xs
inBoundsDecr {k = Z} (InLater y) = InFirst
inBoundsDecr {k = (S k)} (InLater y) = InLater (inBoundsDecr y)

然后在Yes分支中使用它,如下所示:

case inBounds 1 list of
     Yes prf => let prf' = inBoundsDecr prf in
                    doSmth (index 0 list) (index 1 list)
     No _ => doSmthElse

但似乎相当冗长。

那么,在伊德里斯这样做最简洁和/或惯用的方式是什么?

1 个答案:

答案 0 :(得分:3)

如果您有xs的证明可以为您提供有关xs的一些信息,最好使用with代替case。然后编译器可以看到参数可以由证明确定。请参阅教程中的本章:Views and the "with" rule

addHs : List Nat -> Nat
addHs xs with (inBounds 1 xs)
  addHs xs | p = ?hole

p上的模式匹配得到Yes prf,然后Yes (InLater y),然后是Yes (InLater InFirst),并将xs更新为(x :: y :: xs)。因此,您可以轻松使用xy

addHs : List Nat -> Nat
addHs xs with (inBounds 1 xs)
  addHs (x :: y :: xs) | (Yes (InLater InFirst)) = x + y
  addHs xs | (No contra) = 0

问题在于 - 这里无法正常工作。如果检查addHs是否为总计,则编译器会向您发出警告,因为它认为可以到达另一个Yes (InLater p)。不知道为什么,整体检查器不是那么好。但理论上它应该工作正常。 : - )

除了你最初的尝试(可能更详细,但你不太依赖于整体检查),你当然可以添加一个虚拟Yes (InLater p)案例或停在那里并做一些像< / p>

addHs : List Nat -> Nat
addHs xs with (inBounds 1 xs)
  addHs (x :: xs) | (Yes (InLater prf)) = x + (index 0 xs)
  addHs xs | (No contra) = 0

或者有些不安全并断言案件无法访问:

addHs : List Nat -> Nat
addHs xs with (inBounds 1 xs) proof q
  addHs (x :: y :: xs) | Yes (InLater InFirst) = x + y
  addHs (x :: xs) | Yes (InLater p) = assert_unreachable
  addHs xs | No _ = 0