【问题标题】:how to parse a list with foldr in SML如何在 SML 中使用 foldr 解析列表
【发布时间】:2023-04-02 09:50:01
【问题描述】:

假设我有一个列表:

type myList = (string * int) list;

我想使用 foldr 查找此列表的特定元素,例如:

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

我该怎么做?

【问题讨论】:

    标签: sml


    【解决方案1】:

    编写伪代码真的很有帮助。

    明确确定此函数的类型也很有帮助,例如:

    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,该类型都可以相同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-06
      • 1970-01-01
      • 2021-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-01
      • 2014-04-17
      相关资源
      最近更新 更多