1

In this article, this function

let adderGenerator numberToAdd = (+) numberToAdd

has this type signature

int -> (int -> int)

However, when I create this function, the inferred type signature is

int -> int -> int
  1. Are these type signatures different?
  2. If not, how can I annotate my adderGenerator so that it has the first type signature?

Edit 1
This is the best I could come up with so far:

type Generator = int -> (int -> int)
let adderGenerator: Generator = (+)

I don't like how it makes adderGenerator adopt a point-free style.

Edit 2
This seems to work:

let adderGenerator numberToAdd : (int -> int) = (+) numberToAdd
Brett Rowberry
  • 1,030
  • 8
  • 21

1 Answers1

3

The type signatures are the same, the parentheses just help indicate that the body of the function results in a function being returned.

These three forms with the full type annotated are equivalent:

let adderGenerator : int -> int -> int =
    (+)

let adderGenerator (numberToAdd : int) : int -> int =
    (+) numberToAdd

let adderGenerator : int -> int -> int =
    fun numberToAdd -> (+) numberToAdd

The first form is just an alias for + and simply reiterates its type.

The second form is a function declaration that annotates the type of the argument and return type separately.

The third form is a variable assigned an anonymous function.

Only making one argument explicit seems a bit odd to me, however. You can avoid partial application entirely by making both arguments explicit:

let adderGenerator (a : int) (b : int) : int =
    (+) a b

let adderGenerator : int -> int -> int =
    fun a b -> (+) a b
glennsl
  • 28,186
  • 12
  • 57
  • 75