A type signature is a compact description of a value or function’s types. For a function, types appear from left to right: input types first, then the result after the final arrow. For example, int -> int -> int describes a function taking two integers and returning an integer. Type annotations can make those types explicit, while F# type inference can often determine them automatically. section 3.2.2
Read signatures as a chain of inputs and result
The signature int -> int -> int can be read as “take an int, then take another int, then produce an int.” Parentheses disambiguate argument annotations: let add (a:int) (b:int) : int = a + b. Without parentheses, a trailing : int denotes the function’s return type rather than an argument’s type. section 3.2.2
Signatures also reveal how functions compose. List.map has the signature ('T -> 'U) -> 'T list -> 'U list: it needs a conversion function from 'T to 'U, then a list of 'T, and produces a list of 'U. Reading each arrow-separated part makes it easier to choose collection functions that fit together instead of trying combinations at random. section 7.2.3
mapping : ('T -> 'U) -> 'T list -> 'U list
Inspect the generic List.map signature, then match its first input to a conversion function and its second input to a source list. section 7.2.3
A signature can expose an important design choice—or conceal one. A mutable drive function typed string -> unit visibly accepts only a distance and returns no useful value, yet it also depends on and changes hidden gas state. Passing gas explicitly produces a function whose inputs and returned state are visible, making call order and behavior easier to follow. section 4.2.3
Signatures show partial application
An F# function written with two apparent inputs is a chain of single-input functions. add has int -> int -> int; after let addFive = add 5, addFive has int -> int; after addFive 10, the result has type int. The arrows explain why supplying one argument returns another function. section 6.1.1







