4

I am trying to understand difference between these two;

val my_fun = length o List.filter (fn (item) => item = #"a") o String.explode 

This one can be invoked (my_fun "name" will return 1) and works fine. I am trying to understand why following is not working

length o (List.filter (fn (item) => item = #"a" ) (String.explode "name"))

Definition of function composition in sml

f o g = f(g(x))

In the second form what we do is ( I think)

length ([#"a"]) 
John Coleman
  • 51,337
  • 7
  • 54
  • 119
Can
  • 369
  • 4
  • 16
  • You're missing the parameter in the composition definition; `(f o g) x = f(g x)`, or `f o g = fn x => f (g x)`. – molbdnilo Jan 31 '17 at 09:25

1 Answers1

5

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.

John Coleman
  • 51,337
  • 7
  • 54
  • 119