编写伪代码真的很有帮助。
明确确定此函数的类型也很有帮助,例如:
val findElement = fn : string -> myList -> ?
函数应该返回什么类型?在您的伪代码中,您编写了 int result,但 result 在标准 ML 中不能用作内置类型构造函数。那么它应该是什么? int?如果没有匹配的元素,您如何区分任何特定结果和“无结果”?你有什么选择?
尝试解决这个问题,而不是先使用foldr。
由于扫描列表意味着沿其结构递归,因此您可以使用模式匹配编写此函数,将模式分为匹配空列表和匹配非空列表的模式:
fun lookup needle [] = ?
| lookup needle ((key, value) :: haystack) =
if ?
then ?
else ?
- 条件必须将
needle 与每一对的某些内容进行比较,直到匹配。如何比较 SML 中的两个值是否相等?
- 当条件满足时,不需要进行进一步的递归,所以可以返回一个值。如何在 SML 中返回一些东西?
- 当条件不满足时,通过
lookup 调用haystack 继续搜索。调用自己意味着在“else”之后在正文中引用lookup。它到底应该用什么参数调用自己?
了解基本的递归函数是了解foldr 的先决条件。此时,请尝试阅读有关foldr 的信息。我找不到任何关于这方面的好的开放材料,所以我会查找你可用的任何书本形式的学习材料。
就与用foldr 表达lookup 相关的挑战而言:
-
foldr 在找到元素时不会停止递归。
- 您可以通过抛出异常并捕获它来停止它。这有点棘手。
- 您可以让它循环到最后并保留找到的第一个元素。这有点低效。
模板可能如下所示:
fun lookup needle haystack =
foldr (fn ((key, value), acc) => ?) ? haystack
或者你可以在本地命名匿名函数fn ... => ?:
fun lookup needle haystack =
let fun go ((key, value), acc) = ?
in foldr go ? haystack
end
这里? 指的是lookup 返回的类型的值。
无论您使用手动递归还是foldr,该类型都可以相同。