Nick Heiner
Nick Heiner

Reputation: 122432

Type declaration in tuple unpacking

Given a type:

type coords = int * int 

The following works:

# let c : coords = 3, 4;;
val c : coords = (3, 4)

I would also like to be able to do:

# let (x, y) : coords = 3, 4;;
  let (x, y) : coords = 3, 4;;
Error: Syntax error

But it complains about a syntax error on :. Is this syntactically possible?

Upvotes: 5

Views: 3553

Answers (2)

Marcus Junius Brutus
Marcus Junius Brutus

Reputation: 27286

The syntax

let x : t = ...

means that you are, in most cases needlessly, telling the compiler that the type of the name x is t (or maybe you just want to add this type information for readability purposes). In your example:

let (x,y) : coords =

you have to ask yourself: what is the name whose type is coords? Clearly you define no such name, the type of x is int and so is the type of y. There's no name with type coords on the left side. If you already have a coords value, you can split it up as below:

# type coords = int*int ;;
type coords = int * int
# let c:coords = 3,4 ;;
val c : coords = (3, 4)
# let x,y = c;;
val x : int = 3
val y : int = 4

In the above example on the line

let  c: coords = 3,4 ;;

you are actually letting the compiler that the name c should be assigned a coords type (otherwise int*int will be used as the type).

Upvotes: 1

The syntax let x : t = … is the no-argument case of the more general syntax

let f a1 … an : t = …

where t is the return type of the function f. The identifier f has to be just an identifier, you can't have a pattern there. You can also write something like

let (x, y) = …

Here (x, y) is a pattern. Type annotations can appear in patterns, but they must be surrounded by parentheses (like in expressions), so you need to write

let ((x, y) : coords) = …

Note that this annotation is useless except for some cosmetic report messages; x and y still have the type int, and (x, y) has the type int * int anyway. If you don't want coordinates to be the same type as integers, you need to introduce a constructor:

type coords = Coords of int * int
let xy = Coords (3, 4)

If you do that, an individual coordinate is still an integer, but a pair of coordinates is a constructed object that has its own type. To get at the value of one coordinate, the constructor must be included in the pattern matching:

let longitude (c : coords) = match c with Coords (x, y) -> x

Upvotes: 9

Related Questions