asfe
asfe

Reputation: 63

why is a definition like this not producing an error in OCaml?

let f (x :: []) = [1;2];; 

I don't understand the structure of this function. Normally a function is declared like this: let <function name> <arguments> = <function definition> But here we give the function f a constant as an argument, namely [x], and then do nothing with this argument. Instead, we assign the constant [1;2] to the function f?

Upvotes: 0

Views: 107

Answers (2)

octachron
octachron

Reputation: 18912

To illustrate why having patterns in a function definition is useful, here are few examples of exhaustive patterns in arguments. The first common case is tuple:

let f (x,y) = x + y

In the code above,(x,y) is a pattern that binds the first and second element of a couple to the x and y variable respectively.

There is an equivalent construction for records

type vec2 = {x: float; y:float}
let f { x; _ } { y; _ } {x=x'; y = y' } = x +. y +. x' + y'

In this case {x; _}, {y; _ }, { x=x'; y=y'} are both exhaustive patterns.

For ordinary variants, it is less frequent to have useful and exhaustive patterns, but this can happen:

let f (x::_, _ | [], x) = x

Here, in this case we are either extracting the first element of the list in the first element of the tuple if the list is not empty, or the second element of the tuple. Those cases are more frequent when using GADTs or empty types that makes it possible to have some branches of an algebraic not inhabited for a specific subtype. For instance, the pattern in

type empty = |
let f (None:empty option) = ()

is exhaustive because the only possible value of the type empty option is None.

Upvotes: 3

Chris
Chris

Reputation: 36680

utop # let f x :: [] = [1;2];; 
Error: Syntax error

This does give me an error. The following will compile.

let f (x :: []) = [1; 2]

But produces a warning about incomplete pattern match, because a list can have zero or any number of elements. A list with one element is just one specific example.

utop # let f (x :: []) = [1; 2];;
Line 1, characters 6-24:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
_::_::_
val f : 'a list -> int list = <fun>

It's worth noting that [x] is not a constant in a function like this. It is binding the name x to the one element in the list, whatever that happens to be.

Consider:

utop # let foo [x] = x;;
Line 1, characters 8-15:
Warning 8 [partial-match]: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
_::_::_
val foo : 'a list -> 'a = <fun>

utop # foo [42];;
- : int = 42

Of course, this is a silly function, since x is never used by the function. You might just have written the following, using _ to indicate a value that we don't care enough about to give a name to.

let foo [_] = [1; 2]

Upvotes: 1

Related Questions