【问题标题】:Understanding the mechanics of fold_right了解 fold_right 的机制
【发布时间】:2017-11-03 04:52:16
【问题描述】:

问题:定义函数mapf,其第一个参数是一元函数,第二个参数是列表。结果是应用于参数列表的每个元素的函数列表。使用 fold_right 编写单行代码,而不是递归函数。

解决方案:

let mapf fn list = fold_right (fun h t -> fn h :: t) list []

我不明白这是如何解决问题的,因为 fold_right 以递归方式使用列表参数计算函数,因此它返回一个值而不是列表。我也不明白下面的符号是什么意思:

fun h t -> fn h :: t

【问题讨论】:

    标签: ocaml higher-order-functions fold


    【解决方案1】:

    你的两个问题是相关的。 fold_right确实返回一个值,但列表就是一个值!

    :: 运算符将一个新元素添加到列表的开头。所以fold_right这个应用计算出来的值确实是一个列表。

    另一种思考方式可能如下。如果您将fold_right+ 运算符一起使用,您将计算如下值:

    fold_right (+) [1; 2; 3] 0 =>
    1 + 2 + 3 + 0 =>
    6
    

    如果您将fold_right:: 运算符一起使用,您将计算如下值:

    fold_right (::) [1; 2; 3] [] =>
    1 :: 2 :: 3 :: [] =>
    [1; 2; 3]
    

    这不是理论上的,它在 REPL 中的工作方式与此完全一样:

    # List.fold_right (+) [1; 2; 3] 0;;
    - : int = 6
    # List.fold_right (fun a b -> a :: b) [1; 2; 3] [];;
    - : int list = [1; 2; 3]
    

    (您需要编写fun a b -> a :: b,因为:: 表示法实际上不能用作独立函数。不幸的是。)

    请注意,自己使用:: 运算符编写列表是完全合法的:

    # 1 :: 2 :: 3 :: [];;
    - : int list = [1; 2; 3]
    

    更新

    首先,fun x y -> expr 是 OCaml 中“lambda”的符号,即函数字面量。

    函数fun h t -> fn h :: t 有两个值ht。它将函数fn 应用于h,并在t 的前面返回一个带有这个新值的新列表。

    从打字的角度来看,h 的值必须是正确的类型才能传递给fnfn 必须返回正确类型的值才能在列表t 中。

    如果这样更清楚,您可以像这样用括号括起来:fun h t -> (fn h) :: t

    函数fun a b -> a :: b 与此类似,只是它只是将a 直接放入列表b。它不应用任何功能。本质上,它与:: 运算符所做的一样。

    从打字的角度来看,a 必须是正确的类型才能成为列表 b 的元素。

    更新 2

    如果您想了解什么是 lambda,一种看待它的方式是,它只是编写相当小的函数的一种方便方式。您可以在没有 lambda 的情况下轻松编写给定的代码:

    let mapf fn list =
        let helper h t = fn h :: t in
        List.fold_right helper list []
    

    此版本有一个名为 helper 的本地声明函数,而不是 lambda。

    另一种看待它的方式是,所有函数都是 lambdas。写函数的惯用方式:

    let f x y = x + y
    

    只是带有显式 lambda 的版本的方便缩写:

    let f = fun x y -> x + y
    

    所以,实际上,lambda 并不是一种特殊的函数。它与任何其他功能完全一样。这只是一个符号选择。

    【讨论】:

    • 那么你如何解释 fun a b -> a :: b?和乐趣 h t -> fn h :: t)
    • 我会更新我的答案,没有评论空间。
    • 我想我明白了。 ocaml 中的 Lambda 表达式是表达其他函数的某种行为的函数。
    • 这是真的,但看待它的方式有点奇怪。 lambda 只是一个函数,而不是一种特殊的函数。所有函数都使用其他函数,除非它们非常微不足道。
    • 我想说,lambda 只是一个匿名函数。您可以使用let 表示法定义一个函数,或者您可以使用fun 表示法直接将其放入。在任何使用 lambda 的地方,都可以使用普通函数,反之亦然。
    猜你喜欢
    • 1970-01-01
    • 2014-06-18
    • 2015-04-24
    • 2013-12-29
    • 2012-08-06
    • 2018-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多