假设我们有一个list : List a
,我们想要使用它的第一个和第二个元素:
case inBounds 1 list of
Yes prf => doSmth (index 0 list) (index 1 list)
No _ => doSmthElse
不幸的是,这不是类型检查:事实上,prf
是InBounds 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
但似乎相当冗长。
那么,在伊德里斯这样做最简洁和/或惯用的方式是什么?
答案 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)
。因此,您可以轻松使用x
和y
:
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