【问题标题】:F# Function composition with two parameter functionF# 具有两个参数函数的函数组合
【发布时间】:2014-08-04 15:27:39
【问题描述】:

在查看 Microsoft 帮助中的示例之前,我以为我理解了函数组合。它显示了以下示例:

let appendString (string1:string) (string2:string) = string1 + string2
let appendExtension fileExtension = appendString "." >> appendString fileExtension
let fileName = appendExtension "myfile" "txt"

appendExtension 的类型是string -> (string -> string)。这似乎是正确的,因为它是部分应用程序。但是缺少的参数是第一个而不是第二个。这怎么可能?

如果我要写appendExtension 而不作文,我会这样做:

let appendExtension name extension = appendString (appendString name ".") extension

括号中的代码看起来像组合的第一部分,但它是appendString的完整应用。

【问题讨论】:

    标签: f#


    【解决方案1】:

    appendExtension 中的fileExtension 参数是missnamed - 它确实是filename!但当然这在这里并不重要,因为名称只对程序员真正重要。

    如果有疑问,请逐步拆除违规表达式:

    appendExtension "myfile" "txt" =
    (appendExtension "myfile") "txt" =
    // definition of appendExtension - insert "myfile" into `fileExtension` ..
    (appendString "." >> appendString "myfile") "txt" =
    // expand ">>" into "|>" IMHO easiest
    "txt" |> appString "." |> appendString "myfile" =
    // insert in first
    appString "." "txt" |> appendString "myfile" =
    // apply first
    ".txt" |> appendString "myfile" =
    // insert and apply second
    "myfile.txt"
    

    【讨论】:

    • 感谢您的回答。一步一步地做是解决问题的好方法。这显示了名字的力量。正是这个坏名声让我想错了方向。所以我现在看到额外的参数“txt”被添加到左边的函数中,然后这个结果被添加到右边的函数中。既然你已经解释过了,听起来很困难!
    • 如果这对您有所帮助,请将其标记为答案 - 当然,如果您愿意,您可以等待更多答案
    【解决方案2】:

    用最简单的构图理解,即:

    (f >> g) x = g(f(x))
    

    我们有

    let appendExtension s = appendString "." >> appendString s
    
    appendExtension "myfile" "txt"
    => (appendString "." >> appendString "myfile") "txt"
    => appendString "myfile" (appendString "." "txt")
    => appendString "myfile" (".txt")
    => "myfile.txt"
    

    Carsten 已经解释过了。

    您在关于部分应用程序的问题中提出了一些重要的观点,我同意您的观点,这个例子可能是一个可怕的例子,或者至少是一个令人困惑的例子。当我想到部分应用时,我会期望(也许我是唯一一个有这种感觉的人),

    appendExtension ext
    

    将产生一个将扩展名ext 添加到字符串的函数!如果是这样的话,我可以说:

    let addTxt = appendExtension "txt"
    

    所以

    addTxt "myfile"
    => "myfile.txt"
    

    同样,

    appendString s
    

    应该生成将s 添加到其参数的函数。在这种我更喜欢但可能没有其他人喜欢的世界观下,我们有以下推导:

    (appendExtension "txt") "myfile"
    => (appendString "." >> appendString "txt") "myfile"
    => appendString "txt" (appendString "." "myfile")
    => appendString "txt" ("myfile.")
    => "myfile.txt"
    

    我想,无论哪种方式都有效。我喜欢我的方式,因为部分应用更有意义。那么我们如何合理化令人困惑的微软示例呢?这个想法是当他们写的时候:

    appendString s
    

    他们的意思是这是一个将某些东西附加到 s 的函数,而不是那个将 s 附加到某些东西的函数。恕我直言,这是一种可怕且令人困惑的英语阅读方式。他们期待

    appendString "dog"
    

    表示附加到“dog”的函数,但它看起来是附加“dog”的函数。他们为什么这么做?也许他们想要

    appendString "dog" "house"
    

    读起来就像它是从左到右附加的。他们想让它看起来像一个有两个参数的函数。呜呜呜。也许这就是惯例,但在考虑部分应用时要注意这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-16
      • 2013-10-17
      • 2016-05-02
      相关资源
      最近更新 更多