Why does this function accept the 2nd param

Viewed 87

The function aux only has one param n. Why can it accept list at the bottom?

# let length list =
    let rec aux n = function
      | [] -> n
      | _ :: t -> aux (n + 1) t
    in
    aux 0 list;;

    val length : 'a list -> int = <fun>
3 Answers

The function keyword introduces a function which takes a single argument, which it pattern matches.

This is equivalent to:

let length lst =
  let rec aux n lst =
    match lst with
    | [] -> n
    | _ :: t -> aux (n + 1) t
  in
  aux 0 lst

Or...

let length lst =
  let rec aux n = 
    fun lst ->
      match lst with
      | [] -> n
      | _ :: t -> aux (n + 1) t
  in
  aux 0 lst

The function expression produces a function of one argument.

# function [] -> 0 | _ -> 1;;
- : 'a list -> int = <fun>

Now, if you write a function f that takes a parameter n, and whose body contains function, as follows:

# let f n = function [] -> 0 | _ -> n;;
val f : int -> 'a list -> int = <fun>

Then f is a function that takes n and returns a function of a single argument.

# f 3;;
- : '_weak1 list -> int = <fun>

The returned value is a function that takes a list of some unknown type of values, and returns an integer (the _weak prefix is related to Weak Type Variables, this is not important here).

Since the returned value is a function, you can apply it:

# (f 3) ["test"];;
- : int = 3

You can drop the parentheses around f 3 because that's how function application is grouped by default:

# f 3 ["test"];;
- : int = 3

So what looks like a function taking two arguments is in fact a function taking one argument, evaluating to a function to which we apply the second argument.

(See also Currying)

function keyword will match the last argument, even it’s not declared in the left side of =.

Compare with match .. with, the match needs the argument name show up.

Related