我试图理解两者之间的区别;
val my_fun = length o List.filter (fn (item) => item = #"a") o String.explode
Run Code Online (Sandbox Code Playgroud)
这个可以被调用(my_fun“name”将返回 1)并且工作正常。我试图理解为什么以下不起作用
length o (List.filter (fn (item) => item = #"a" ) (String.explode "name"))
Run Code Online (Sandbox Code Playgroud)
sml中函数组合的定义
f o g = f(g(x))
Run Code Online (Sandbox Code Playgroud)
在第二种形式中我们所做的是(我认为)
length ([#"a"])
Run Code Online (Sandbox Code Playgroud)
您似乎将函数组合与函数应用混淆了。
组合是一个高阶函数,它接受两个兼容类型的函数f和g,并返回另一个函数——该函数通过首先将 应用于g一个值,然后应用于f结果来计算。o是一个内置运算符,但如果你想自己定义组合,它会是这样的
fun compose (f,g) x = f(g(x))
Run Code Online (Sandbox Code Playgroud)
它具有类型(这正是您在 REPL 中fn : ('a -> 'b) * ('c -> 'a) -> 'c -> 'b键入时获得的类型)。(op o);请注意,返回值是compose,'c -> 'b它是一个函数类型。
length o List.filter (fn (item) => item = #"a") o String.explode
Run Code Online (Sandbox Code Playgroud)
非常有意义,因为类型是兼容的并且组合是右关联的。
另一方面,正如您已经注意到的,
length o (List.filter (fn (item) => item = #"a" ) (String.explode "name"))
Run Code Online (Sandbox Code Playgroud)
将相当于
length o [#"a"]
Run Code Online (Sandbox Code Playgroud)
这确实没有道理。用列表组成一个函数意味着什么?列表不是函数。应用于 该列表确实有意义length,这似乎正是您所期望的。
应用程序只是并置,所以您需要做的就是编写
length (List.filter (fn (item) => item = #"a" ) (String.explode "name"))
从那里减少length [#"a"]到 1。
如果你想编写自己的apply函数,你可以这样写:
def apply f x = f x
Run Code Online (Sandbox Code Playgroud)
这可能会让您觉得表面上相似compose,但其类型却截然不同:fn : ('a -> 'b) -> 'a -> 'b。组合涉及应用,但它们不是同一回事。