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