问题描述
type myList = (string * int) list;
我想使用文件夹查找此列表的特定元素,例如:
fun findElement (element : string) (list : myList) : int result =
if needed_element is equal current_list_element then return current_list_element
else continue checking the rest of the list
else return -1
我该怎么做?
解决方法
编写伪代码会很有帮助。
明确确定该函数的类型也很有帮助,例如:
val findElement = fn : string -> myList -> ?
函数应返回哪种类型?在伪代码中,您编写了int result
,但是result
在Standard ML中不能用作内置类型构造函数。那应该是什么? int
?如果没有匹配的元素怎么办?如何区分任何特定结果和“无结果”?您有什么选择?
请尝试解决此问题,而无需先使用foldr
。
由于扫描列表意味着沿其结构递归,因此可以使用模式匹配来编写此功能,将模式分为与空列表匹配的模式和与非空列表匹配的模式:
fun lookup needle [] = ?
| lookup needle ((key,value) :: haystack) =
if ?
then ?
else ?
- 条件必须将
needle
与每一对的值进行比较,直到一个匹配。您如何比较SML中两个相等的值? - 满足条件时,无需执行进一步的递归,因此可以返回一个值。一个人如何用SML返回某些内容?
- 不满足条件时,
lookup
在haystack
上进行调用以继续搜索。自称是指在身体内部lookup
之后的else
。究竟应该用什么参数来称呼自己?
了解基本的递归函数是了解foldr
的前提。此时,请尝试阅读有关foldr
的信息。我找不到专门针对此的好的开放材料,因此我将查找您可以使用的任何书形学习材料。
关于用lookup
表达foldr
带来的挑战:
-
foldr
在找到元素时不会停止递归。 - 您可以通过引发异常并捕获来停止它。这有点棘手。
- 您可以让它循环到最后并保留找到的第一个元素。这有点低效率。
模板可能看起来像:
fun lookup needle haystack =
foldr (fn ((key,value),acc) => ?) ? haystack
或者您可以在本地为匿名函数fn ... => ?
命名:
fun lookup needle haystack =
let fun go ((key,acc) = ?
in foldr go ? haystack
end
此处?
指的是lookup
返回的类型的值。
无论您使用手动递归还是foldr
,该类型都可以相同。