1

使用 Idris 进行测试驱动开发的第 9 章介绍了以下数据类型和removeElem功能。

import Data.Vect

data MyElem : a -> Vect k a -> Type where
   MyHere  : MyElem x (x :: xs)
   MyThere : (later : MyElem x xs) -> MyElem x (y :: xs)

-- I slightly modified the definition of this function from the text.
removeElem : (value : a) -> (xs : Vect (S n) a) -> (prf : MyElem value xs) -> Vect n a
removeElem value (value :: ys) MyHere         = ys
removeElem value (y :: ys)    (MyThere later) = removeElem value (y :: ys) (MyThere later)

以下作品:

*lecture> removeElem 1 [1,2,3] MyHere
[2, 3] : Vect 2 Integer

但是,几分钟后以下调用仍在运行:

*lecture> removeElem 2 [1,2,3] (MyThere MyHere)

我猜为什么编译这么慢?

4

1 回答 1

2

removeElem你读的第二种情况

removeElem value (y :: ys)    (MyThere later) = removeElem value (y :: ys) (MyThere later)

右侧与左侧完全相同;所以你的递归发散了。这就是评估挂起的原因。

请注意,如果您声明removeElem应该是总的,那么 Idris 会发现此错误:

total removeElem : (value : a) -> (xs : Vect (S n) a) -> (prf : MyElem value xs) -> Vect n a
removeElem value (value :: ys) MyHere         = ys
removeElem value (y :: ys)    (MyThere later) = removeElem value (y :: ys) (MyThere later)

这导致编译时错误

RemoveElem.idr第 9 行第 0 列:

Main.removeElem由于递归路径,可能不是全部Main.removeElem

于 2017-06-21T01:54:11.443 回答