目前,我正在通过Edwin Brady的“使用Idris进行类型驱动开发”文本。不用说,文本列出了SplitList和splitList(封面函数)的代码。但是,我想知道文本中给出的封面函数是否可以简化为我在下面生成的封面函数 - 这不能按预期工作。有人可以让我知道为什么我的splitList不起作用?我收到的错误消息在下面进一步生成。非常感谢。
data SplitList : List ty -> Type where
Null : SplitList [ ]
Singleton : SplitList [x]
Pair : (lhs: List ty) -> (rhs: List ty) -> SplitList (lhs ++ rhs)
splitList : (xs: List ty) -> SplitList xs
splitList [ ] = Null
splitList [x] = Singleton
splitList xs =
let
mid = div (List.length xs) 2
lhs = List.take mid xs
rhs = List.drop mid xs
in
Pair lhs rhs
键入检查./foo.idr foo.idr:53:11: 检查具有预期类型的splitList的右侧时 SplitList xs
两者之间的类型不匹配 SplitList(lhs ++ rhs)(对lhs rhs的类型) 和 SplitList xs(预期类型)
具体做法是: 类型不匹配 lhs ++ rhs 和 XS 孔:Main.splitList
答案 0 :(得分:4)
此错误消息的原因是Idris没有看到xs = lhs ++ rhs
,您必须说服Idris。
首先,让我们将上述事实证明是一个单独的引理:
total
takeDropAppend : (n : Nat) -> (xs : List ty) -> xs = List.take n xs ++ List.drop n xs
takeDropAppend Z _ = Refl
takeDropAppend (S n) [] = Refl
takeDropAppend (S n) (x :: xs) = cong $ takeDropAppend n xs
现在我们可以按如下方式使用它:
total
splitList : (xs: List ty) -> SplitList xs
splitList [ ] = Null
splitList [x] = Singleton
splitList xs =
let
mid = divNatNZ (List.length xs) 2 SIsNotZ
in
rewrite takeDropAppend mid xs in
Pair (List.take mid xs) (List.drop mid xs)
我将div
更改为divNatNZ
以使该功能成为总计并采用快捷方式,将lhs
和rhs
替换为其定义。我应该使用(更高效)List.splitAt
标准函数,但它会使证明变得复杂。