如何在SML中使用文件夹解析列表

问题描述

假设我有一个列表:

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返回某些内容?
  • 不满足条件时,lookuphaystack上进行调用以继续搜索。自称是指在身体内部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,该类型都可以相同。