Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Quick Reference

A one-page cheat sheet for the Flix language. Each section links to the relevant chapter for full details.

Program structure

/// Doc comment. Ordinary comments start with //.
def main(): Unit \ IO =
    println("Hello, world!")

Expressions are separated with ;. def defines a function, let a local (see Functions):

def area(w: Int32, h: Int32): Int32 = w * h

def greeting(name: String): String \ IO =
    let msg = "Hello, ${name}!";
    println(msg);
    msg

Anonymous functions use ->: x -> x + 1. Pipelines use |>: l |> List.length |> println.

Primitive types

Unit, Bool, Char, String, Int8, Int16, Int32, Int64, BigInt, Float32, Float64, BigDecimal (see Primitives).

Common operators: + - * / %, == != < <= > >=, and or not, :: (list cons), ::: (list append).

Branching

if (x < 0) {
    "negative"
} else if (x == 0) {
    "zero"
} else {
    "positive"
}

See If-Then-Else.

Enums and pattern matching

enum Shape {
    case Circle(Int32)
    case Rectangle(Int32, Int32)
}

def area(s: Shape): Int32 = match s {
    case Shape.Circle(r)       => 3 * (r * r)
    case Shape.Rectangle(h, w) => h * w
}

Enums can be parametric: enum Tree[a] { case Leaf(a), case Node(Tree[a], Tree[a]) }. Use case _ => ... as a wildcard. Tuples destructure the same way (see Enums and Pattern Matching):

match pair {
    case (1, _) => "starts with one"
    case _      => "something else"
}

Lists

let l1 = 1 :: 2 :: 3 :: Nil;
let l2 = l1 ::: 4 :: Nil;
match l1 {
    case Nil     => 0
    case _ :: xs => 1 + List.length(xs)
}

See Lists.

Strings

let name = "Ada";
let msg = "Hello, ${name}!";  // string interpolation

See String Interpolation.

Records

let r = {name = "Ada", age = 36};
r#name                            // field access
{name = "Grace" | r}              // update a field
{+lang = "Flix" | r}              // add a field
{-age | r}                        // drop a field

See Records.

Modules

use Calc.sum                      // use a name
use Calc.{mul, neg}               // use several names
use Calc.{sum => plus}            // use a name under another name

mod Calc {
    pub def sum(x: Int32, y: Int32): Int32 = x + y
    pub def mul(x: Int32, y: Int32): Int32 = x * y
    pub def neg(x: Int32): Int32 = -x
}

A use goes before the declarations of its file or module. A module is declared once, and is private to the module it is declared in unless it is a pub mod, which goes in a file of its own: pub mod Museum.Entrance in src/Museum/Entrance.flix.

See Modules and Declaring Modules.

Traits and instances

trait Show[t] {
    pub def show(x: t): String
}

instance Show[Int32] {
    pub def show(x: Int32): String = "${x}"
}

See Traits.

Effects

Pure functions carry the empty effect \ {}; impure ones declare what they use, e.g. \ IO. Effect-polymorphic functions abstract over it with a variable (see Effect System):

def inc(x: Int32): Int32 \ {} = x + 1
def twice(f: Int32 -> Int32 \ ef, x: Int32): Int32 \ ef = f(f(x))

Option and Result

match opt {
    case Some(x) => x
    case None    => 0
}

match res {
    case Ok(v)  => v
    case Err(e) => 0
}

Loops

def main(): Unit \ IO =
    let l = 1 :: 2 :: 3 :: Nil;
    foreach (x <- l)
        println(x)

See Foreach.