在我查看微软帮助中的示例之前,我认为我理解了函数组合。它显示了以下示例:
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
的完整应用程序。<
因此,我们删除其中一个参数以进行部分应用,从而实现一个功能。
但第一个参数被删除而不是第二个参数。
这怎么可能?
答案 0 :(得分:1)
fileExtension
中的appendExtension
参数未命名 - 确实是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"
答案 1 :(得分:1)
使用最简单的构图理解,即:
(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"
读起来就像是从左到右追加。他们想让它看起来像一个双参数函数。 Ewwww。也许这就是惯例,但是在考虑部分应用时,应该注意这一点。