sml理解函数组合

Can*_*Can 4 ml sml

我试图理解两者之间的区别;

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)

Joh*_*man 5

您似乎将函数组合与函数应用混淆了。

组合是一个高阶函数,它接受两个兼容类型的函数fg,并返回另一个函数——该函数通过首先将 应用于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。组合涉及应用,但它们不是同一回事。