错误的原因是因为这一行:
contains l1 l2 = starts l1 l2;
与上一行没有什么不同:
contains l1 (hd::tl) = contains l1 tl
这两行都表达了相同的匹配模式。你可以看到这个,你可以写:contains l1 (l2 as (hd::tl)) = contains l1 tl
这会使解释器感到困惑,因为您告诉它,在这种模式的情况下:contains l1 l2,做两件不同的事情,即:
starts l1 l2; 和
contains l1 tl
在此处获得解决方案的方法是删除contains 的最后一行,因为它是多余的。
在第二行中,您的目的是现在循环第二个列表的初始元素,直到您到达第二个列表的“当前元素”与第一个列表的第一个元素匹配的点。 如果是这种情况,则调用start else继续循环。
考虑val first_list = [2,3,4] 和val second_list = [1,2,2,2,2,3,4,5,6]
所以第二行中的contains 必须首先循环遍历second_list 的元素以查看第一个元素是否匹配。如果它们匹配,则调用 start。所以你得到以下细分:
2=1? => false 从而循环到第二个元素
2=2? => true 因此调用start 以查看从那时起我们是否有匹配列表。
由于start 在检查3=2? => false 时将返回false,因此您现在必须继续循环contains 并重复此过程。它必须循环直到到达second_list 中的最后一个2。此时对比会是这样的:
2=2? => true 因此调用start 来检查连续元素是否匹配。
start 现在将评估为 true,如下所示:
3=3? => true
4=4? => true
5=5? => true --> 此时start 将返回true,它也应该是 contains 的返回值。如果start 在任何时候返回false,那么您需要继续循环。
最终,您将模式匹配 first_list 和 [],这将被您的第一行捕获。
注意:
start 是正确的,但要避免这种模式:if a=b then true else false,而只写 a=b:
所以像这样重写start的最后一行:
| starts (h1::t1) (h2::t2) = ((h1=h2) andalso (starts t1 t2));