Pattern Matching

Let Pattern Match

In addition to the pattern match construct, a let-binding can be used to destruct a value. For example:

let (x, y, z) = (1, 2, 3)

Binds the variables x, y, and z to the values 1, 2, and 3, respectively.

Any exhaustive pattern may be used in a let-binding. For example:

let (x, Foo(y, z)) = (1, Foo(2, 3))

is legal provided that the Foo constructor belongs to a type where it is the only constructor.

The following let-bindings are illegal because they are not exhaustive:

let (1, 2, z) = ...
let Some(x) = ...

The Flix compiler will reject such non-exhaustive patterns.

Match Lambdas

Pattern matches can also be used with lambda expressions. For example:

List.map(match (x, y) -> x + y, (1, 1) :: (2, 2) :: Nil)

is equivalent to:

List.map(w -> match w { case (x, y) => x + y }, (1, 1) :: (2, 2) :: Nil)

As for let-bindings, such pattern matches must be exhaustive.

Note the difference between the two lambda expressions:

let f = (x, y, z) -> x + y + z + 42i32
let g = match (x, y, z) -> x + y + z + 42i32

Here f is a function that expects three Int32 arguments,whereas g is a function that expects one three tuple (Int32, Int32, Int32) argument.

Let* (Do-notation)

Flix supports a feature similar to do-notation in Haskelland for-comprehensions in Scala.

The following monadic code:

use Option.flatMap;
let o1 = Some(21);
let o2 = Some(42);
flatMap(x -> flatMap(y -> Some(x + y), o2), o1)

May be expressed more concisely as:

use Option.flatMap;
let* o1 = Some(21);
let* o2 = Some(42);
Some(o1 + o2)

where each let* corresponds to a flatMap use.