【问题标题】:Position of anonymous function’s parameters in SML’s foldl匿名函数参数在 SML 的 foldl 中的位置
【发布时间】:2021-09-20 10:40:49
【问题描述】:

我需要编写一个函数,它接受一个字符串列表并在列表中找到最大的字符串。在平局的情况下,它应该返回最接近列表末尾的字符串。问题是它需要使用 List.foldl 遍历列表,并且不能使用递归调用,除了 List,foldl 的库函数中的调用。 以下代码运行良好。

fun longest_string2 str_list =
     List.foldl(fn (x, acc) => if String.size x >= String.size acc then x else acc) "” str_list

如果我在 REPL 中运行 longest_string2 ["Apple", "ball", "Bpple”];,我会得到 val it = "Bpple" : string 但是,如果我如下反转匿名函数的参数,我会得到val it = "Apple" : string。 由于匿名函数是通过名称而不是位置访问元素,为什么这会有所不同?

【问题讨论】:

    标签: sml


    【解决方案1】:

    List.foldl的定义是

    fun foldl (f: 'a*'b->'b) (acc: 'b) (l: 'a list): 'b =
      case l of
        [] => acc
      | x::xs => foldl f (f(x,acc)) xs
    

    如果您反转匿名函数的参数,您的函数将变为以下内容:(如果我误解了您的问题,请纠正我)

    fun longest_string2 str_list =
         List.foldl(fn (acc, x) => if String.size x >= String.size acc then x else acc) "” str_list
    

    如果您现在将 ["Apple", "ball", "Bpple”] 作为参数传递给 longest_string2foldl 函数将与您的列表模式匹配 x::xs,其中 x 是“Apple”,xs 是 ["ball" , "Bpple"]。当您使用 f(x, acc) 计算更新的累加器时,xacc 被交换。换句话说,在您的匿名函数中(使用反向参数),您会假设第一个参数将为””,第二个参数为Apple,但List.foldl的实现将传递f(“Apple”, “”)。在这种情况下,您的匿名函数将“Apple”标记为“acc”“”标记为“x” .

    【讨论】:

      【解决方案2】:

      @3123 回答了这个问题最多,但没有直接在问题中回答这个陈述。

      由于匿名函数是按名称访问元素而不是 位置,为什么会有所不同?

      foldl 接受一个函数,该函数接受一个 tuple 作为其参数,它是位置的。

      如果我们真的想实现这一点,我们可以定义一个以记录作为参数的折叠函数:

      fun namedFold _ acc [] = acc
        | namedFold f acc (x::xs) =
            namedFold f (f {acc=acc, x=x}) xs;
      

      然后称它为:

      namedFold (fn { acc, x } => acc + x) 0 [1,2,3,4]
      

      或如:

      namedFold (fn { x, acc } => acc + x) 0 [1,2,3,4]
      

      得到同样的结果。

      但是namedFold 的类型是fn :({acc: 'a, x: 'b} -> 'a) -> 'a -> 'b list -> 'a,并且基本上不可能轻松地将现有函数传递给它。使用 foldl 定义的方式,我们可以轻松地将之前调用的 namedFold 重写为:

      foldl op+ 0 [1,2,3,4]
      

      因为op+foldl 的第一个参数具有相同的签名。

      【讨论】:

        猜你喜欢
        • 2011-10-24
        • 1970-01-01
        • 1970-01-01
        • 2013-01-25
        • 1970-01-01
        • 1970-01-01
        • 2021-02-19
        • 1970-01-01
        • 2013-01-17
        相关资源
        最近更新 更多