继续使用仅一个列表的折叠来解决这个问题:
fun isInList (xs, z) = foldl (fn (x, acc) => ...) ... xs
其中acc 是foldl 在每次递归调用时累积的值。
第一个... 必须反映列表中值x 的存在是否对函数的结果产生影响,或者是否任何先前考虑的元素产生影响(使用acc 作为代理) .
第二个... 是一个bool,表示xs 为空时的默认值,是foldl 执行的递归的基本情况。
请注意,标准 ML 中的折叠是一个急切的过程:它会遍历整个列表,直到得出元素存在的结论。因此,平均而言,List.exists 是搜索单个列表的更好组合子。在惰性求值语言中,折叠可能是等价的。
(可选) 考虑如何将这两个递归调用交织在一起并创建成对折叠。实际上,有一个名为 ListPair.foldl 的函数是这样工作的:
(* Finds the largest positive integer in two lists, or 0 *)
fun max3 (x, y, z) = Int.max (x, Int.max(y, z))
fun maxTwoLists (xs, ys) = ListPair.foldl max3 0 (xs, ys)
但它有一个烦人的副作用:
val huh = maxTwoLists ([1,2,3], [1,2,3,4]) (* gives 3 *)
因此,如果您想遍历两个列表并成对查看它们的元素,并在另一个列表结束时继续查找一个列表,并在满足或不再满足您的标准时停止折叠,您正在处理List.foldl 和 ListPair.foldl 均不支持开箱即用的递归方案。如果这不是需要折叠的学校练习,这将是一种解决方案:
fun isInList (xs, z) = List.exists (fn x => x = z) xs
fun isInBoth (x::xs, y::ys, z) =
x = z andalso isInList (y::ys, z) orelse (* no needs to look at more xs *)
y = z andalso isInList (x::xs, z) orelse (* no needs to look at more ys *)
isInBoth (xs, ys, z) (* keep looking in both *)
| isInBoth ([], ys, z) = false (* not found in xs *)
| isInBoth (xs, [], z) = false (* not found in ys *)
将递归模式抽象为类似于ListPair.foldl 的函数可能没那么有用。