joshua
joshua

Reputation: 997

The difference between parentheses in curried function types

What's the different of those return type ??

val fn1 : int −> (int −> (int −> int))
val fn2: (int −> int) −> (int −> int)

This creates a function of type

int -> int -> int    meaning    int -> (int -> int)

is that right? They have the same meaning without bracket!

Upvotes: 1

Views: 257

Answers (2)

Chris
Chris

Reputation: 36680

Functions in SML take one argument and return one value. End of story.

Well, not quite.

When we need to pass multiple arguments to a function there are two ways to do this. You can either pass a tuple or record or some other aggregate data structure to the function. This is a single value, but it is composed of multiple pieces of data.

fun f (x, y) = x * 3 + y

Where currying comes from is that functions are values as well, and functions return a single value. That value can be a function. So we could write:

val f = fn x => fn y => x * 3 + y

That's tedious, so we can write it as:

fun f x y = x * 3 + y

This is very amenable to partial application: binding that function returned by applying one argument to f to a new name and then calling it on the remaining argument.

val g = f 3;
val h = g 1; (* 10 *)

A function like f could be given the type int -> (int -> int) because the describes what it does: given an int value return a function that takes an int and returns an int. But int -> int -> int describes this equivalently.

Now, if you see (int -> int) -> int, that describes something different. That means the function takes a function as an argument and returns an int.

An example of a function that does that:

fun g f = 1 + f 5

Because that int -> int function represents one value passed in as an argument, the parentheses cannot be removed from the type signature (int -> int) -> int.

Upvotes: 0

sshine
sshine

Reputation: 16145

The function type of fn1 is, as you say, equivalent to int -> int -> int -> int.

When you have multiple curried arguments like fn1 a b c, then fn1 a is a function of type int -> int -> int, and fn1 a b is a function of type int -> int. So fn1 could also be seen as a function that returns a function that returns a function that returns an int. Adding the parentheses like int -> (int -> (int -> int)) highlights that interpretation.

The function fn2 is different: It takes a function of type int -> int as argument and returns another function of type int -> int.

Upvotes: 3

Related Questions