Reference manual

Valid expressions and types in Par.

Primitives

TypeExamplesDescription
Int 3, 2589, -15* Integer numbers, unbounded.
Float 71.439, .5, -0.01 Floating point (real) numbers, 64-bit, double-precision.
Bool true, false Boolean values.
Char 'a', 'm', '\t' One character, represented as a unicode codepoint. See escape sequences.
String "hello", "", "some line\n" Zero or more ordered characters. See escape sequences.
String `raw string`, ``, `\w+` A string delimited by backticks is a raw string. In a raw string, no escaping is allowed, and backslashes are regular, literal characters. Raw strings are generally used for regular expressions.
() () The unit type/value, which represents the lack of a value. Used for functions that don't return anything useful.
Atom @foo, @a, @"hey there" Zero or more ordered characters, allocated only once and never garbage collected. Similar to Symbols in Ruby, but rarely used, except when interoperating with Erlang.

* – More precisely, integer literals are of type A ~ Num, meaning any type that implements the Num interface. Both Int and Float implement Num, so an integer can act as either an Int or a Float.

Types

TypeDescription
Int, Float, Bool, (), etc. A concrete type. See primitives above and expressions below for examples.
A, B, ..., Z A single uppercase letter is a type variable, which can represent any concrete type.
Set<A> A concrete generic type Set parametrized by type A.
[A] Short-hand for List<A>.
Mod.Foo, Mod.Bar<A> Access an exported concrete/generic type in the module Mod.
(A, B) Tuple consisting of two values, the first of type A and second of type B.
(A, B, C) Tuple consisting of three values, the first of type A, second of type B, and third of type C.
() -> R Function that accepts no arguments and returns a value of type type R.
A -> R Function that accepts an argument of type A and returns a value of type R.
(A, B) -> R Function that accepts two arguments of types A and B and returns a value of type R.
A ~ Num A type variable representing a type A such that A implements the interface Num. See interfaces.
A ~ Num ~ Ord A type variable representing a type A such that A implements both the interfaces Num and Ord. See interfaces.
{ foo: A } An anonymous record, which is a collection of fields, each with a name and value. This record contains one field with a name of foo and value of type A.
{ foo: A, bar: B } Anonymous record containing two fields: foo with a value of type A and bar with a value of type B.
{ foo: A, bar: B | R } Anonymous record containing at least two fields: foo with a value of type A and bar with a value of type B. R is a type variable representing the remaining fields, if any.
A<B> Any generic type A parametrized by type B.
A<B> ~ Collection Any generic type A<B> that implements the interface Collection.
A<B> ~ Collection ~ Concat Any generic type A<B> that implements both interfaces Collection and Concat.
(A) Same as type A, but just parenthesized. Necessary to resolve ambiguity. For instance, ((Int, Bool)) -> String is a function that accepts one argument, a tuple (Int, Bool), and returns a String.

Expressions

In the table below, expr1, expr2, etc. are sub-expressions, and type1 is the type of expr1, type2 is the type of expr2, etc.

pat1, pat2, etc. are patterns, and pat_type1 is the type matched by pat1, pat_type2 is the type matched by pat2, etc.

ExpressionReturn typeDescription
[] [A] Empty list.
[expr1, expr2, ...] [type1] List with elements. Requires type1 == type2 == ...
[expr1, expr2, ... | expr3] type3 Returns a new list beginning with the elements expr1, expr2, etc. and ending with all elements in the existing list expr3 (which isn't modified).

Requires type3 == [type1] == [type2] == .... In other words, type3 must be a list of elements of some type, which we'll call E. type1, type2, etc. must all be E.

#[] Set<A> Empty set.
#[expr1, expr2, ...] Set<type1> Set with elements. Requires type1 == type2 == ...
{ expr1 => expr2, expr3 => expr4, ... } Map<type1, type2> Create a hash map, where expr1 is a key that maps to value expr2, expr3 is a key that maps to value expr4, etc. Requires type1 == type3 == ... and type2 == type4 == ....
() () Unit value, represents the lack of a value.
(expr1) type1 Parenthesized expression that evalutes to the result of expr1.
(expr1, expr2, ...) (type1, type2, ...) Tuple, must contain two or more elements.
{ foo = expr1, bar = expr2, ... } { foo : type1, bar : type2, ... } Create an anonymous record, must contain one or more fields.
Bar { foo = expr1, bar = expr2, ... } Bar Create a struct of type Bar, which must've been defined earlier. The struct Bar must have fields foo of type type1, bar of type type2, etc.
{ foo = expr1, bar = expr2, ... | expr3 } type3 Create a new record that has the fields foo, bar, etc. plus all other fields in the existing record expr3 (which isn't modified).

type3 must be { foo : type1, bar : type2, ... | R } for some R. In other words, expr3 must already contain fields foo and bar with appropriate types. expr3 can contain other fields too.

{ foo := expr1, bar := expr2, ... | expr3 } { foo : type1, bar : type2, ... | type3 } Create a new record that has the fields foo, bar, etc. plus all other fields in the existing record expr3 (which isn't modified).

type3 must be { foo : A, bar : B, ... | R } for some A, B, and R. In other words, expr3 must already contain fields foo and bar, but they can be of any type. This syntax allows you to change the types of existing fields.

expr1.foo Type of field foo in expr1. Access field foo in expr1. type1 must be { foo : A | R } for some types A and R.
.foo { foo : A | R } -> A A function that accepts one argument, a record with field foo, and returns the value of foo. The record may have additional fields.
let pat1 = expr1 () Matches expr1 to pattern pat1, raising an exception if the match fails. Assigns variables in pat1 appropriately. Requires pat_type1 == type1.
let foo(pat1, pat2, ...) = expr1 () Assigns foo to a function that accepts arguments of type pat_type1, pat_type2, etc. and returns the value given by expr1. foo is of type (pat_type1, pat_type2, ...) -> type1.
foo Type of value that foo refers to. The variable foo. foo may be prefixed by a module name, like Mod.foo, which accesses the exported constant or function foo within module Mod.
Foo Type of value that Foo refers to. The enum variant Foo. Foo may be prefixed by a module name, like Mod.Foo, which accesses the exported variant Foo within module Mod.
if expr1 then expr2 () If expr1 evaluates to true, evaluates expr2. Returns the unit value, since there's no guarantee expr1 is true. Requires type1 == Bool.
if expr1 then expr2 else expr3 type2 If expr1 evaluates to true, evaluates and returns expr2. Otherwise, evaluates and returns expr3. Requires type1 == Bool and type2 == type3.
if let pat1 = expr1 then expr2 () If pat1 matches expr1, evaluates expr2, assigning any variables in pat1 appropriately. Returns the unit value, since there's no guarantee pat1 matches expr1. Requires pat_type1 == type1.
if let pat1 = expr1 then expr2 else expr3 type2 If pat1 matches expr1, evaluates and returns expr2, assigning any variables in pat1 appropriately. Otherwise, evaluates and returns expr3. Requires pat_type1 == type1 and type2 == type3.
match expr1 { pat2 => expr2, pat3 => expr3, ... } type2 If pat2 matches expr1, then executes and returns expr2, assigning any variables in pat2 appropriately. Otherwise, if pat3 matches expr1, then executes and returns expr3. Repeats for each pattern until one matches. If no patterns match, raises an exception. Requires type1 == pat_type2 == pat_type3 == ... and type2 == type3 == ....
|-| expr1 () -> type An anonymous function that accepts no arguments and returns the value given by expr1.
|pat1, pat2, ...| expr1 (pat_type1, pat_type2, ...) -> type1 An anonymous function that accepts arguments of type pat_type1, pat_type2, etc. and returns the value given by expr1.
expr1() Return type of expr1. Calls the function given by expr1 with no arguments. Requires type1 == () -> R for some R.
expr1(expr2, expr3, ...) Return type of expr1. Calls the function given by expr1 with arguments expr2, expr3, etc. Requires type1 == (type2, type3, ...) -> R for some R.

If any of expr2, expr3, etc. is _, then this becomes a partial application. All arguments that aren't _ are evaluated, and a new function is returned that accepts the _ arguments in order, and calls the function given by expr1 appropriately. For instance, expr1(_, expr2, _) is equivalent to |a, c| f(a, b, c), where f is the result of evaluating expr1 and b is the result of evaluating expr2.

expr1 |> expr2 Return type of expr2. Same as calling expr2(expr1).
expr1 |> expr2(expr3, expr4, ...) Return type of expr2. Same as calling expr2(expr1, expr3, expr4, ...).
expr1 && expr2
expr1 || expr2
Bool Boolean and/or operations. Requires type1 == type2 == Bool.
expr1 == expr2
expr1 != expr2
Bool Equal and not equal operations. Requires type1 == type2.
expr1 < expr2
expr1 > expr2
expr1 <= expr2
expr1 >= expr2
Bool Less than (or equal to) and greater than (or equal to) operations. Requires type1 == type2 == A ~ Ord
expr1 + expr2
expr1 - expr2
expr1 * expr2
type1 Addition, subtraction, or multiplication operation. Requires type1 == type2 == A ~ Num.
expr1 / expr2 Float Division operation. Requires type1 == type2 == A ~ Num.
expr1 % expr2 Int Remainder operation. Requires type1 == type2 == Int.
expr1 ++ expr2 type1 Concatenates expr1 and expr2. See Concat in the interfaces section for a detailed description. Requires type1 == type2 == A ~ Concat.
expr1 : sig Type given by type signature sig Specifies an explicit type for expression expr1. sig is a type signature, which is any valid type in the types section.
-expr1 type1 Aritmetic negative operation. Requires type1 == A ~ Num.
!expr1 Bool Logical negation operation. Requires type1 == Bool.
$expr1 Int Returns the unicode codepoint (i.e. the numeric representation) of the character given by expr1. Requires type1 == Char.
raise expr1 A Raises an exception, halting execution unless it's caught. Requires type1 == Exception1. raise returns a type variable A so it can be used in any context without type errors.
try expr1 catch { pat2 => expr2, pat3 => expr3, ... } type1 Tries to evaluate expr1. If successful, returns the value given by expr1. If expr1 raises an exception, tries to match pat2 with expr1. If pat2 matches, evaluates and returns expr2. Otherwise, if pat3 matches, evaluates and returns expr3. Repeats for each pattern until one matches.

If no patterns match, the exception isn't caught and continues propagating up the call stack. Requires type1 == type2 == type3 == ... and pat_type2 == pat_type3 == Exception.

ensure expr1 after expr2 type2 Ensures that expr1 is evaluated after expr2, even if expr2 raises an exception. Returns the result of expr2.
discard expr1 () Discards the return value of expr1.
assume expr1 A Subverts the type system, letting expr1 act as any type. Use with extreme caution; there should be no need for this unless interoperating with Erlang.
@lists:map/2 (A, B) -> C References the Erlang standard library function map in the lists module, where 2 is the function's arity. Any native Erlang function can be specified in this way by changing the names and arity appropriately.

Note that native calls are inherently unsafe, as we don't know the argument types or return type. We allow two arguments of any two types, and return a value of any type.

@lists:map(expr1, expr2) A Same as above, except we're calling the native function and the arity is implied by the number of arguments.

Patterns

In the table below, pat1, pat2, etc. are sub-patterns, and pat_type1 is the type matched by pat1, pat_type2 is the type matched by pat2, etc.

PatternMatches typeDescription
Any primitive. Type of the primitive. Matches an exact primitive value.
[] [A] Matches an empty list.
[pat1, pat2, ...] [pat_type1] Matches a list with elements. pat1 matches the first element, pat2, matches the second element, etc. Requires pat_type1 == pat_type2 == ....
[pat1, pat2, ... | pat3] pat_type3 Matches initial elements of a list and the remainder of the list. pat1 matches the first element, pat2 matches the second, etc. pat3 matches the remainder of the list.

Requires pat_type3 == [pat_type1] == [pat_type2]. In other words, pat_type3 must be a list of elements of some type, which we'll call E. pat_type1, pat_type2, etc. must all be E.

() () Matches the unit value, which represents the lack of a value.
(pat1) pat_type1 Parenthesized pattern that matches what pat1 matches.
(pat1, pat2, ...) (pat_type1, pat_type2, ...) Matches a tuple of elements. pat1 matches the first element, pat2 matches the second, etc.
foo A A variable name like foo matches any value, and assigns that value to the variable if the pattern match is successful.
_ A Matches anything, but doesn't assign a reference to it.
Foo Type of Foo (enum type). Matches the enum variant Foo. Requires that Foo accepts no arguments. Foo may be prefixed by a module name, like Mod.Foo, which accesses the exported variant Foo within module Mod.
Foo(pat1, pat2, ...) Return type of Foo (enum type). Matches the enum variant Foo that accepts arguments. pat1 is matches the first argument, pat2 matches the second, etc. Foo may be prefixed by a module name, like Mod.Foo, which accesses the exported variant Foo within the module Mod.

Builtin interfaces

The table below lists builtin interfaces and their purpose. An interface specifies a set of functions or operators, and all types that satisfy the interface provide implementations for those functions or operators.

InterfaceImplemented byDescription
Num Int, Float A numeric type. Can be operated on by +, -, *, /.
Ord Int, Float, Char, String A type that's ordered. Can be operated on by >, <, >=, <=.
Concat String, [A], Set<A>, Map<K, V> A type that can be concatenated/merged using the ++ operator. For strings and lists, a ++ b is a concatenation. For sets, it's a union operation. For maps, it's a merge operation where keys in b overwrite keys in a. See the docs for more details.

Operator precedence

In order from least precedence to highest precedence.

Operator
|>
||
&&
==, !=, >, >=, <, <=
+, -, ++, --
*, /, %
:
Unary -, !, $, raise, discard, assume

Escape sequences

May be used in String and Char literals to denote special characters.

SequenceDescription
\b Backspace
\d Delete
\e Escape
\f Form feed
\n Newline
\r Carriage return
\t Tab
\v Vertical tab