You seem to be confusing function composition with function application.
Composition is a higher-order function which takes two functions, f
and g
, of compatible types and returns another function -- the function which is computed by first applying the g
to a value and then applying f
to the result. o
is a built-in operator, but if you wanted to define composition yourself it would be something like
fun compose (f,g) x = f(g(x))
this has type fn : ('a -> 'b) * ('c -> 'a) -> 'c -> 'b
(which is exactly the type you get when you type (op o);
in the REPL). Note that the return value of compose
is 'c -> 'b
, which is a function type.
length o List.filter (fn (item) => item = #"a") o String.explode
makes perfect sense since the types are compatible and composition is right-associative.
On the other hand, as you already note,
length o (List.filter (fn (item) => item = #"a" ) (String.explode "name"))
would be equivalent to
length o [#"a"]
That really doesn't make sense. What would it even mean to compose a function with a list. A list isn't a function. It does make sense to apply length
to that list, which is what you seem to expect.
Application is simply juxtaposition, so all you would need to do is write
length (List.filter (fn (item) => item = #"a" ) (String.explode "name"))
Which reduces to length [#"a"]
and from thence to 1.
If you wanted to write your own apply
function you would write:
def apply f x = f x
This might strike you as superficially similar to compose
but its type is radically different: fn : ('a -> 'b) -> 'a -> 'b
. Composition involves application, but it isn't the same thing.