我正在使用 PAKCS Curry 编译器,版本 3.3.0。
这是 Curry 中的一个简单的列表反转功能(它也适用于 Haskell):
rev :: [a] -> [a]
rev [] = []
rev (x : xs) = (rev xs) ++ [x]
让我们尝试反转函数,即找到一个反转为 [1..5] 的列表 l:
> rev l =:= [1 .. 5] where l free
{l=[5,4,3,2,1]} True
...hang...
库里能解方程真是太好了。然而,它进入了一个无限循环,寻找更多的解决方案。
这是 Prolog 中的等价谓词:
rev([], []).
rev([X | L], M) :- rev(L, LR), append(LR, [X], M).
Prolog 谓词也无法以相反的方向终止:
?- rev(L, [1, 2, 3, 4, 5]).
L = [5, 4, 3, 2, 1] ;
...hang...
在 Prolog 中,我可以通过添加 L 及其倒数具有相同长度的约束来帮助终止:
rev([], []).
rev([X | L], M) :- same_length([X | L], M), rev(L, LR), append(LR, [X], M).
有了这个额外的约束,谓词在两个方向上都终止。
在 Curry 中,是否可以添加类似的约束,或者以其他方式帮助查询终止?
我尝试定义一个具有类似 same_length 约束的反函数:
same_length :: [a] -> [b] -> Bool
same_length [] [] = True
same_length (_ : _) [] = False
same_length [] (_ : _) = False
same_length (_ : xs) (_ : ys) = same_length xs ys
rev :: [a] -> [a]
rev [] = []
rev (x : xs) = (rev xs) ++ [x]
rev2 :: Data a => [a] -> [a]
rev2 b@(rev a) | same_length a b = a
但是它没有帮助:'rev2 [1 .. 5]' 也找到了一个解决方案,然后无法终止。