【发布时间】:2017-11-29 04:40:06
【问题描述】:
我在使用下面的代码时遇到了一些问题。本质上我想创建一个切片类型。动机来自 Python,其中切片为[start:end:step],用于从列表中切出子列表。这在概念上与索引序列[start, start+step, start+2*step, ..., end] 相同。
我尝试捕获它的方式是Slice n,可以应用于Vect (n+m) a。基本构造函数FwdS 将创建一个非零步长的切片(proof stepNZ)。 SLen 构造函数将现有切片的Vect 大小要求增加其step(使用stepOf 计算)。同样,SStart 将切片的 Vect 大小要求增加 1。
那么最终的值在概念上对应于:
start := # of SStart in slice
stop := start + (# of SLen) * step
step := constructor argument in FwdS
如果切片是[start:stop:step]。
mutual
data Slice : Nat -> Type where
FwdS : (step : Nat) -> {stepNZ : Not (step = Z)} -> Slice Z
SLen : (x : Slice len) -> Slice (len + (stepOf x))
SStart : Slice len -> Slice (S len)
stepOf : Slice n -> Nat
stepOf (FwdS step) = step
stepOf (SLen slice) = stepOf slice
stepOf (SStart slice) = stepOf slice
length : Slice n -> Nat
length (FwdS step ) = Z
length (SLen slice) = let step = stepOf slice
len = length slice
in len + step
length (SStart slice) = length slice
select : (slice: Slice n) -> Vect (n+m) a -> Vect (length slice) a
select (FwdS step) xs = []
select (SStart slice) (x :: xs) = select slice xs
select (SLen slice) (xs) = ?trouble
问题在于最后一个模式。我不确定问题出在哪里 - 如果我尝试在 xs 上区分大小写,我会同时得到 [] 和 (_::_) 不可能。理想情况下,我想让这个案例读到这样的内容:
select (SLen slice) (x :: xs) = let rec = drop (stepOf slice) (x::xs)
in x :: (select slice rec)
并让 Idris 认识到,如果第一个参数是 SLen 构造函数,则第二个参数不能是 []。我的直觉是,在SLen 级别,Idris 不明白它已经有证据证明stepOf slice 不是Z。但我不确定如何测试这个想法。
【问题讨论】:
标签: idris