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

Introduction

Welcome to The Halcyon Book, the official documentation for the Halcyon programming language. Halcyon is a compiled, strongly typed, functional programming language. It is compiled to WebAssembly, a portable binary format that can run in the browser.

Installation

IDE Setup

Visual Studio Code

TODO

Helix

In your Helix config folder (~/.config/helix/ by default), create languages.toml if it does not already exist. Add a grammar and language entry for Halcyon:

[[grammar]]
name = "halcyon"
source = { git = "https://git.lgatlin.dev/logan/tree-sitter-halcyon.git", rev = "main" }

[[language]]
name = "halcyon"
scope = "source.hc"
file-types = ["hc"]
grammar = "halcyon"
comment-tokens = ["--"]
block-comment-tokens = { start = "(*", end = "*)" }

Next, fetch and build the grammar. If this is your first time building grammars this will take several minutes.

helix -g fetch
helix -g build

Finally, download the highlight queries to your runtime directory:

mkdir -p ~/.config/helix/runtime/queries/halcyon
wget https://git.lgatlin.dev/logan/tree-sitter-halcyon/raw/branch/main/queries/highlights.scm \
  -O ~/.config/helix/runtime/queries/halcyon/highlights.scm

Hello World

Time to write your first Halcyon program. Create a file named main.hc containing the following:

<span class='hljs-keyword'>module</span> hello_world =
  <span class='hljs-keyword'>do</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span> <span class='hljs-string'>"Hello World!"</span>
<span class='hljs-keyword'>end</span>

Langauge Reference

Here you will find a description of the major features of the Halcyon langauge.

Anatomy of a program

Lets examine a Halcyon program piece by piece. Here is a Fizz Buzz program:

<span class='hljs-keyword'>module</span> example =
  <span class='hljs-keyword'>let</span> fizzbuzz = <span class='hljs-keyword'>fn</span> <span class='hljs-params'>number</span> <span class='hljs-params'>max</span> <span class='hljs-keyword'>=&gt;</span>
    <span class='hljs-punctuation'>(</span><span class='hljs-keyword'>match</span> <span class='hljs-punctuation'>(</span>number <span class='hljs-operator'>%</span> <span class='hljs-variable constant_'>3</span><span class='hljs-punctuation'>,</span> number <span class='hljs-operator'>%</span> <span class='hljs-variable constant_'>5</span><span class='hljs-punctuation'>)</span> <span class='hljs-keyword'>with</span>
      | <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>0</span><span class='hljs-punctuation'>,</span> <span class='hljs-variable constant_'>0</span><span class='hljs-punctuation'>)</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-string'>"FizzBuzz"</span>
      | <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>0</span><span class='hljs-punctuation'>,</span> _<span class='hljs-punctuation'>)</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-string'>"Fizz"</span>
      | <span class='hljs-punctuation'>(</span>_<span class='hljs-punctuation'>,</span> <span class='hljs-variable constant_'>0</span><span class='hljs-punctuation'>)</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-string'>"Buzz"</span>
      | <span class='hljs-punctuation'>(</span>_<span class='hljs-punctuation'>,</span> _<span class='hljs-punctuation'>)</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-title class_'>format</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>integer</span> number<span class='hljs-punctuation'>)</span>
	<span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span><span class='hljs-punctuation'>;</span>
    <span class='hljs-keyword'>if</span> number <span class='hljs-operator'>&lt;</span> max <span class='hljs-keyword'>then</span>
      <span class='hljs-title function_'>fizzbuzz</span> <span class='hljs-punctuation'>(</span>number <span class='hljs-operator'>+</span> <span class='hljs-variable constant_'>1</span><span class='hljs-punctuation'>)</span> max
    <span class='hljs-keyword'>else</span>
      <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span>

  <span class='hljs-keyword'>do</span> <span class='hljs-title function_'>fizzbuzz</span> <span class='hljs-variable constant_'>1</span> <span class='hljs-variable constant_'>30</span>
<span class='hljs-keyword'>end</span>

Modules

A Halcyon source file contains one or more modules.

<span class='hljs-keyword'>module</span> example =
<span class='hljs-comment'>(* ... *)</span>
<span class='hljs-keyword'>end</span>

Modules contain four kinds of statements:

  • let defines a variable
  • do executes an expression (like a main function)
  • type defines a new type, or type alias (described later)
  • import imports a function from another language, such as JavaScript or C

Note

Statements do not require whitespace or semicolons to separate them.

A module acts as a namespace. To access a value or type from another module, the :: symbol is used. For example, std::println refers to the println function in the std module.

Functions

Functions are a kind of expression. They are defined using the syntax fn [parameters] => [body]. Here, a function is defined with two parameters number and max.

<span class='hljs-keyword'>let</span> fizzbuzz = <span class='hljs-keyword'>fn</span> <span class='hljs-params'>number</span> <span class='hljs-params'>max</span> <span class='hljs-keyword'>=&gt;</span>

The body of a function is a single expression after the => operator. The functions return value is the value of this expression, there is no return keyword.

The syntax for function calls is significantly different from other languages. If the argument to a function is a literal (numbers, strings, booleans, arrays, structures, etc), no parenthesis are required.

<span class='hljs-keyword'>do</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span> <span class='hljs-string'>"Hello World!"</span>

If an argument is an expression, it must be wrapped in parenthesis.

<span class='hljs-keyword'>do</span> <span class='hljs-title function_'>add_integers</span> <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>5</span> <span class='hljs-operator'>-</span> <span class='hljs-variable constant_'>1</span><span class='hljs-punctuation'>)</span> <span class='hljs-variable constant_'>4</span>

An alternative way to call a function is with the |> operator. This operator calls a function on the right with an argument on the left.

<span class='hljs-keyword'>do</span> <span class='hljs-string'>"Hello World!"</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span>

It is even possible to combine both syntax. The |> operator has a lower precedence than a regular function call, so the argument to the left of it will come last.

<span class='hljs-keyword'>do</span> <span class='hljs-string'>"World!"</span>
  <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>concatenate</span> <span class='hljs-string'>"Hello "</span>
  <span class='hljs-comment'>(* Equivalent to:
   * string::concatenate "Hello " "World!" *)</span>
  <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span>
  <span class='hljs-comment'>(* Prints "Hello World!" *)</span>

Match expressions

The match expression is the most important control flow in Halcyon. It is similar to, but much more powerful than switch statements in other languages. A match expression consists of an expression to match on (the discriminant), and a list of cases. Here, the program is matching on the tuple (number % 3, number % 5):

<span class='hljs-punctuation'>(</span><span class='hljs-keyword'>match</span> <span class='hljs-punctuation'>(</span>number <span class='hljs-operator'>%</span> <span class='hljs-variable constant_'>3</span><span class='hljs-punctuation'>,</span> number <span class='hljs-operator'>%</span> <span class='hljs-variable constant_'>5</span><span class='hljs-punctuation'>)</span> <span class='hljs-keyword'>with</span>
      | <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>0</span><span class='hljs-punctuation'>,</span> <span class='hljs-variable constant_'>0</span><span class='hljs-punctuation'>)</span> <span class='hljs-keyword'>=&gt;</span> "FizzBuzz"
      | <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>0</span><span class='hljs-punctuation'>,</span> _<span class='hljs-punctuation'>)</span> <span class='hljs-keyword'>=&gt;</span> "Fizz"
      | <span class='hljs-punctuation'>(</span>_<span class='hljs-punctuation'>,</span> <span class='hljs-variable constant_'>0</span><span class='hljs-punctuation'>)</span> <span class='hljs-keyword'>=&gt;</span> "Buzz"
      | <span class='hljs-punctuation'>(</span>_<span class='hljs-punctuation'>,</span> _<span class='hljs-punctuation'>)</span> <span class='hljs-keyword'>=&gt;</span> format<span class='hljs-punctuation'>::</span>integer number<span class='hljs-punctuation'>)</span>

A match case has the syntax | [pattern] => [expression]. The discriminant is compared with each pattern in order. The entire expression evaluates to the case of the first pattern matched. For example, consider the case:

| <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>0</span><span class='hljs-punctuation'>,</span> <span class='hljs-variable constant_'>0</span><span class='hljs-punctuation'>)</span> <span class='hljs-keyword'>=&gt;</span> "FizzBuzz"

The pattern (0, 0) is matched only when the discriminant is equal to (0, 0). However, this pattern:

| <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>0</span><span class='hljs-punctuation'>,</span> _<span class='hljs-punctuation'>)</span> <span class='hljs-keyword'>=&gt;</span> "Fizz"

only requires the first value in the tuple to be 0. The _ symbol, or any identifier, is a 'wildcard' that matches anything.

This match expression evaluates to "FizzBuzz" if number is a multiple of 3, and 5, "Fizz" if number is only a multiple of 3, "Buzz" if number is only a multiple of 5, and format::integer number otherwise. This is string is then printed.

<span class='hljs-operator'>|&gt;</span> std<span class='hljs-punctuation'>::</span>println<span class='hljs-punctuation'>;</span>

Note

The ; symbol is an operator like in bash. Its purpose is to join together two expressions.

If expressions

The if expression works exactly the same as in other lanuguages, with the exception that the else clause is mandatory. This is because if is an expression, not a statement, and so it must evaluate to something in either case. Here, the program recursively calls fizz_buzz if number is less than max. Otherwise, the function returns () (similar to void or None in other languages).

if number <span class='hljs-operator'>&lt;</span> max <span class='hljs-keyword'>then</span>
      fizzbuzz <span class='hljs-punctuation'>(</span>number <span class='hljs-operator'>+</span> <span class='hljs-variable constant_'>1</span><span class='hljs-punctuation'>)</span> max
    <span class='hljs-keyword'>else</span>
      <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span>

Comments

There are two kinds of comments, single line and block. A single line comments begin with two dashes --. Block comments begin with (* and end in *), and may be nested inside other block comments. It is conventional to begin every line of a block comment with *, but this is not required.

<span class='hljs-comment'>-- This is a line comment</span>
<span class='hljs-comment'>(*
 * This is a block comment,
 * it can span multiple lines<span class='hljs-comment'>
   (*
    * This is a nested block comment
   *)</span>
*)</span>

Non-features

Mutable variables

Every variable in Halcyon is constant. Once a variable is defined, it cannot be changed.

Loops

Halcyon does not have for or while loops. Instead, all looping is done through recursion. The compiler performs tail call optimization to convert recursive functions into simple loops. This means that your program will not overflow its stack no matter how deeply it recurses.

Warning

Tail call optimizization is only possible in certain circumstances. It is only done when the recursive call is the last operation performed in the function. The fizzbuzz example is tail recursive.

Exceptions and null

Halcyon does not have exceptions or null. Functions that may fail instead return an opt or result. These are covered more in-depth in their respective doc pages.

Operators Reference

The following is the full list of operators in Halcyon, in order of their precedence:

SymbolDescription
(unary) - -.arithmetic negation
(unary) notlogical negation
* *.multiplication
/ /.division
%modulus
+ +.addition
- -.subtraction
(function call)
>> <<function composition
xorlogical XOR
orlogical OR
|>function pipe
== != <= >= < >comparison
andlogical AND
;

Warning

Currently, the comparison operators are only defined for primitive types. Comparing other data types will cause a crash.

Operators are regular functions that are defined in the std module. An operator's function can be accessed by surrounding it in parenthesis, like ( + ) 1 2 == 1 + 2

Warning

Always put whitespace around an operator when it is in parenthesis. (*) is parsed as the beginning of a comment, while ( * ) is the multiplication operator.

Integer and Real Operators

Because operators are functions, the operators for integers and reals are different.

IntegersReals
++.
--.
**.
//.
%

The ; Operator

The ; simply returns the value to the right. It is useful for chaining together function calls with side effects.

Example

<span class='hljs-keyword'>do</span>  <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span> <span class='hljs-string'>"old pond"</span><span class='hljs-punctuation'>;</span>
    <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span> <span class='hljs-string'>"frog leaps in"</span><span class='hljs-punctuation'>;</span>
    <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span> <span class='hljs-string'>"water's sound"</span><span class='hljs-punctuation'>;</span>
    <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span> <span class='hljs-string'>" - Bashō'"</span>

The |> Operator

|> is the pipe operator. This operator calls a function on the right with an argument on the left. The pipe operator helps create function "pipelines", where the return value of one function becomes the parameter of the next function.

Note

Function calls have a higher precedence than |>

Example

<span class='hljs-keyword'>do</span> <span class='hljs-title class_'>format</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>real</span> <span class='hljs-variable constant_'>3.14159</span>
    <span class='hljs-comment'>(* Convert real to string *)</span>
    <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>concatenate</span> <span class='hljs-string'>"pi = "</span>
    <span class='hljs-comment'>(* Prepend "pi = " *)</span>
    <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span>
    <span class='hljs-comment'>(* Prints "pi = 3.14159" *)</span>

The >> and << operator

The >> and << operators perform function composition. Given two functions f and g, f >> g is equivalent to fn x => g(f(x)). The reverse operation f << g is equivalent to fn x => f(g(x)).

The Type System

Halcyon is a statically typed language with full type inference. Type inference means that the types of functions and variables do not need to be written, they can be guessed by the compiler. Compare a function which adds two integers written in C versus in Halcyon:

int add_integers(int x, int y) {
  return x + y;
}
<span class='hljs-keyword'>let</span> add_integers = <span class='hljs-keyword'>fn</span> <span class='hljs-params'>x</span> <span class='hljs-params'>y</span> <span class='hljs-keyword'>=&gt;</span> x <span class='hljs-operator'>+</span> y

Type annotations can be added using :, but they are not necessary. It is an error for a type annotation to be different from the actual type.

<span class='hljs-keyword'>let</span> add_integers <span class='hljs-punctuation'>:</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-type'>integer</span> <span class='hljs-operator'>-&gt;</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-type'>integer</span> =
  <span class='hljs-keyword'>fn</span> <span class='hljs-punctuation'>(</span>x <span class='hljs-punctuation'>:</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-type'>integer</span><span class='hljs-punctuation'>)</span> <span class='hljs-punctuation'>(</span>y <span class='hljs-punctuation'>:</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-type'>integer</span><span class='hljs-punctuation'>)</span> <span class='hljs-keyword'>=&gt;</span> x <span class='hljs-operator'>+</span> y

This book will often provide type annotations for clarity's sake, but this is not intended to imply they are best practice or required.

Primitive types

The following is a list of the primitive types, as well as their equivalents in C:

Halcyon typeC type
() or unitvoid
integerint or long
realdouble
booleanbool
glyphwchar_t
stringwchar_t[]

Note

The glyph and string types are UTF-8 encoded, not ASCII.

Note

Primitive types are defined in the std module

Example

<span class='hljs-keyword'>let</span> nothing <span class='hljs-punctuation'>:</span> <span class='hljs-type'>(</span><span class='hljs-type'>)</span> = <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span>
<span class='hljs-keyword'>let</span> life <span class='hljs-punctuation'>:</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-type'>integer</span> = <span class='hljs-variable constant_'>42</span>
<span class='hljs-keyword'>let</span> pi <span class='hljs-punctuation'>:</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-type'>real</span> = <span class='hljs-variable constant_'>3.14159</span>
<span class='hljs-keyword'>let</span> yes <span class='hljs-punctuation'>:</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-type'>boolean</span> = <span class='hljs-built_in'>true</span>
<span class='hljs-keyword'>let</span> grade <span class='hljs-punctuation'>:</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-type'>glyph</span> = <span class='hljs-string'>'A'</span>
<span class='hljs-keyword'>let</span> greeting <span class='hljs-punctuation'>:</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-type'>string</span> = <span class='hljs-string'>"Hello world!"</span>

Arrays

An array is a list of values of the same type, and that has a variable length. To define an array, use square brackets:

<span class='hljs-keyword'>let</span> numbers <span class='hljs-punctuation'>:</span> [<span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-type'>integer</span>] = [<span class='hljs-variable constant_'>1</span><span class='hljs-punctuation'>,</span> <span class='hljs-variable constant_'>2</span><span class='hljs-punctuation'>,</span> <span class='hljs-variable constant_'>3</span><span class='hljs-punctuation'>,</span> <span class='hljs-variable constant_'>4</span>]

Tuples

A tuple is a list of values that may be different types, and has a fixed length. To define a tuple, use parenthesis:

<span class='hljs-keyword'>let</span> single_tuple = <span class='hljs-punctuation'>(</span><span class='hljs-string'>"alone"</span><span class='hljs-punctuation'>,</span><span class='hljs-punctuation'>)</span>
<span class='hljs-keyword'>let</span> grocery_list = <span class='hljs-punctuation'>(</span><span class='hljs-string'>"eggs"</span><span class='hljs-punctuation'>,</span> <span class='hljs-string'>"bacon"</span><span class='hljs-punctuation'>,</span> <span class='hljs-string'>"milk"</span><span class='hljs-punctuation'>)</span>
<span class='hljs-keyword'>let</span> favorite_numbers = <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>42</span><span class='hljs-punctuation'>,</span> <span class='hljs-variable constant_'>2.718</span><span class='hljs-punctuation'>,</span> <span class='hljs-string'>'∞'</span><span class='hljs-punctuation'>)</span>
<span class='hljs-keyword'>let</span> list_of_lists = <span class='hljs-punctuation'>(</span>grocery_list<span class='hljs-punctuation'>,</span> favorite_numbers<span class='hljs-punctuation'>)</span>

Function types

A fundamental rule in Halcyon is that every function has a single parameter. This is achieved using a process called currying. Understanding this concept is extremely important, so lets work through an example. Consider this function:

<span class='hljs-keyword'>let</span> add_integers = <span class='hljs-keyword'>fn</span> <span class='hljs-params'>x</span> <span class='hljs-params'>y</span> <span class='hljs-params'>z</span> <span class='hljs-keyword'>=&gt;</span> x <span class='hljs-operator'>+</span> y <span class='hljs-operator'>+</span> z

The compiler will automatically transform add_integers into the following:

<span class='hljs-keyword'>let</span> add_integers =
  <span class='hljs-keyword'>fn</span> <span class='hljs-params'>x</span> <span class='hljs-keyword'>=&gt;</span>
    <span class='hljs-keyword'>fn</span> <span class='hljs-params'>y</span> <span class='hljs-keyword'>=&gt;</span>
      <span class='hljs-keyword'>fn</span> <span class='hljs-params'>z</span> <span class='hljs-keyword'>=&gt;</span> x <span class='hljs-operator'>+</span> y <span class='hljs-operator'>+</span> z

Let us see how the expression add_integer 1 2 3 is evaluated. First, substitute the variable name for its definition:

<span class='hljs-punctuation'>(</span><span class='hljs-keyword'>fn</span> x <span class='hljs-keyword'>=&gt;</span> <span class='hljs-keyword'>fn</span> y <span class='hljs-keyword'>=&gt;</span> <span class='hljs-keyword'>fn</span> z <span class='hljs-keyword'>=&gt;</span> x <span class='hljs-operator'>+</span> y <span class='hljs-operator'>+</span> z<span class='hljs-punctuation'>)</span> <span class='hljs-variable constant_'>1</span> <span class='hljs-variable constant_'>2</span> <span class='hljs-variable constant_'>3</span>

Next, call the outermost function with the first argument 1:

<span class='hljs-punctuation'>(</span><span class='hljs-keyword'>fn</span> y <span class='hljs-keyword'>=&gt;</span> <span class='hljs-keyword'>fn</span> z <span class='hljs-keyword'>=&gt;</span> <span class='hljs-variable constant_'>1</span> <span class='hljs-operator'>+</span> y <span class='hljs-operator'>+</span> z<span class='hljs-punctuation'>)</span> <span class='hljs-variable constant_'>2</span> <span class='hljs-variable constant_'>3</span>

Repeat with the next two arguments 2 and 3:

<span class='hljs-punctuation'>(</span><span class='hljs-keyword'>fn</span> y <span class='hljs-keyword'>=&gt;</span> <span class='hljs-keyword'>fn</span> z <span class='hljs-keyword'>=&gt;</span> <span class='hljs-variable constant_'>1</span> <span class='hljs-operator'>+</span> y <span class='hljs-operator'>+</span> z<span class='hljs-punctuation'>)</span> <span class='hljs-variable constant_'>2</span> <span class='hljs-variable constant_'>3</span>
<span class='hljs-punctuation'>(</span><span class='hljs-keyword'>fn</span> z <span class='hljs-keyword'>=&gt;</span> <span class='hljs-variable constant_'>1</span> <span class='hljs-operator'>+</span> <span class='hljs-variable constant_'>2</span> <span class='hljs-operator'>+</span> z<span class='hljs-punctuation'>)</span> <span class='hljs-variable constant_'>3</span>
<span class='hljs-variable constant_'>1</span> <span class='hljs-operator'>+</span> <span class='hljs-variable constant_'>2</span> <span class='hljs-operator'>+</span> <span class='hljs-variable constant_'>3</span>
<span class='hljs-variable constant_'>6</span>

The type of a function is written as a -> b, where a is the parameter type, and b is the return type. The -> operator, like =>, is right associative. This means that a -> b -> c is interpreted as a -> (b -> c). The type of add_integers in the example above is:

integer -> integer -> integer -> integer

Advanced types

Some types must be explicitly defined and given a name before they may be used.

Structures

A structure is like a tuple with named values. It is similar to a struct or class in other languages. Unlike primitive types, identical structures with different names not the same type. Structures are defined using type statements:

<span class='hljs-keyword'>type</span> Vector2 = <span class='hljs-punctuation'>{</span> x <span class='hljs-punctuation'>:</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-type'>real</span><span class='hljs-punctuation'>,</span> y <span class='hljs-punctuation'>:</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-type'>real</span> <span class='hljs-punctuation'>}</span>

<span class='hljs-keyword'>let</span> origin <span class='hljs-punctuation'>:</span> <span class='hljs-type'>Vector2</span> = <span class='hljs-punctuation'>{</span>
  x = <span class='hljs-variable constant_'>0.0</span><span class='hljs-punctuation'>,</span>
  y = <span class='hljs-variable constant_'>0.0</span><span class='hljs-punctuation'>,</span>
<span class='hljs-punctuation'>}</span>
<span class='hljs-keyword'>let</span> x = origin.x
<span class='hljs-keyword'>let</span> y = origin.y

Note

In rare cases, type inference for structures may fail. This is because some structures may be exactly the same except for their name. For this reason, it is best practice to write type annotations for structures.

Sum types

Sum types are similar to enums in other languages.

<span class='hljs-keyword'>type</span> Class = <span class='hljs-title function_'>Knight</span> | <span class='hljs-title function_'>Mage</span> | <span class='hljs-title function_'>Rogue</span>

<span class='hljs-keyword'>let</span> class_greeting = <span class='hljs-keyword'>fn</span> <span class='hljs-params'>class</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span>
  <span class='hljs-punctuation'>(</span><span class='hljs-keyword'>match</span> class <span class='hljs-keyword'>with</span>
    | <span class='hljs-title function_'>Knight</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-string'>"I am a knight"</span>
    | <span class='hljs-title function_'>Mage</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-string'>"I am a mage"</span>
    | <span class='hljs-title function_'>Rogue</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-string'>"I am a rogue"</span><span class='hljs-punctuation'>)</span>

<span class='hljs-keyword'>do</span>
  <span class='hljs-title function_'>class_greeting</span> Knight<span class='hljs-punctuation'>;</span>
  <span class='hljs-title function_'>class_greeting</span> Mage<span class='hljs-punctuation'>;</span>
  <span class='hljs-title function_'>class_greeting</span> Rogue

A sum type may contain data attached to one of its variants. Imagine you are writing a function safe_divide that checks if the denominator is zero. Using sum types, we can show that this function may fail to return a number:

<span class='hljs-keyword'>type</span> Result = <span class='hljs-title function_'>Ok</span> <span class='hljs-keyword'>of</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-type'>real</span> | <span class='hljs-title function_'>DivisionError</span>

<span class='hljs-keyword'>let</span> safe_divide = <span class='hljs-keyword'>fn</span> <span class='hljs-params'>numerator</span> <span class='hljs-params'>denominator</span> <span class='hljs-keyword'>=&gt;</span>
  <span class='hljs-keyword'>match</span> denominator <span class='hljs-keyword'>with</span>
    | <span class='hljs-variable constant_'>0</span> <span class='hljs-keyword'>=&gt;</span> DivisionError
    | _ <span class='hljs-keyword'>=&gt;</span> <span class='hljs-title function_'>Ok</span> <span class='hljs-punctuation'>(</span>numerator <span class='hljs-operator'>/.</span> denominator<span class='hljs-punctuation'>)</span>

The Result type defines two constructors, Ok and DivisionError. Because DivisionError contains no data, it is actually just a constant with the type Result. The Ok constructor does contain data, so it is a function with the type real -> Result. Sum types are extremely flexible; Halcyon uses them as a substitute for null pointers, exceptions, and sub-types.

Note

A result type already exists in the standard library result module, including lots of useful functions for working with results. See also: the opt module

Implicit Polymorphism

We discussed earlier that Halcyon has full type inference. What do you think the type of this function will be inferred to be?

<span class='hljs-keyword'>let</span> identity <span class='hljs-comment'>(* ? -&gt; ? *)</span> = <span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-keyword'>=&gt;</span> a

The function identity simply returns whatever its parameter is. There are no context clues forcing a to be any type in particular, and so identity is implicitly polymorphic. In simple terms, this means that its argument may be any type:

<span class='hljs-keyword'>do</span>
  <span class='hljs-title function_'>identity</span> <span class='hljs-variable constant_'>1</span><span class='hljs-punctuation'>;</span>
  <span class='hljs-title function_'>identity</span> <span class='hljs-built_in'>false</span><span class='hljs-punctuation'>;</span>
  <span class='hljs-title function_'>identity</span> <span class='hljs-string'>"foo"</span>

The exact type of identity is '0 -> '0, where '0 is a type variable. Type variables are a placeholder type that gets replaced when a function is actually called. A functions type may have any number of type variables.

<span class='hljs-keyword'>let</span> first = <span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-params'>b</span> <span class='hljs-keyword'>=&gt;</span> a
<span class='hljs-keyword'>let</span> second = <span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-params'>b</span> <span class='hljs-keyword'>=&gt;</span> b

<span class='hljs-keyword'>do</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span> <span class='hljs-punctuation'>(</span><span class='hljs-title function_'>first</span> <span class='hljs-string'>"foo"</span> <span class='hljs-variable constant_'>2</span><span class='hljs-punctuation'>)</span>
<span class='hljs-keyword'>do</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span> <span class='hljs-punctuation'>(</span><span class='hljs-title function_'>second</span> <span class='hljs-built_in'>false</span> <span class='hljs-string'>"bar"</span><span class='hljs-punctuation'>)</span>

Here, first has the type '0 -> '1 -> '0, while second has the type '0 -> '1 -> '1.

Explicit Polymorphism

Types can contain type variables just like functions. Polymorphic types are called type functions, and follow slightly different rules from regular types.

The standard library defines the opt type, similar to the Result type above except that it can contain any type, not just real. Let's see how it is implemented:

<span class='hljs-keyword'>module</span> opt = 
  <span class='hljs-keyword'>type</span> t = <span class='hljs-keyword'>fn</span> <span class='hljs-type'>a</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-title function_'>Some</span> <span class='hljs-keyword'>of</span> <span class='hljs-type'>a</span> | <span class='hljs-title function_'>None</span>
<span class='hljs-keyword'>end</span>

Here, opt, is not a type per se, but rather a function that returns a type. The parameters to a type function (in this case a) are other types. When you use a polymorphic type, the compiler will infer the correct type parameter for you.

<span class='hljs-keyword'>let</span> safe_divide = <span class='hljs-keyword'>fn</span> <span class='hljs-params'>numerator</span> <span class='hljs-params'>denominator</span> <span class='hljs-keyword'>=&gt;</span>
  <span class='hljs-keyword'>match</span> denominator <span class='hljs-keyword'>with</span>
    | <span class='hljs-variable constant_'>0</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span>None
    | _ <span class='hljs-keyword'>=&gt;</span> <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Some</span> <span class='hljs-punctuation'>(</span>numerator <span class='hljs-operator'>/</span> denominator<span class='hljs-punctuation'>)</span>
<span class='hljs-comment'>(* safe_divide : integer -&gt; (opt::t integer) *)</span>

Modules

Modules are how code is organized in Halcyon: all variables, functions, and types must be inside a module. There are a number of built-in modules supported by Halcyon. These are implicitly in scope in all Halcyon programs.

The following modules are planned, but remain unimplmented

std

std is a module that contains the 6 primitive types, as well as some functions that most Halcyon programs will need access to.

Primitives


integer

The 64 bit two's complement integer type. The maximum 64 bit signed integer is 9,223,372,036,854,775,807. Integer literals can be written in multiple ways

LiteralRepresentation
9_999Decimal number
0b1111Binary number (prefixed with 0b)
0o777Octal number (prefixed with 0o)
0xFFHexadecimal number (prefixed with 0x)

Base prefixes and hexadecimal digits are case insensitive. Integer literals may have underscore _ characters in any position.


real

A 64 bit floating point number, similar to float in C.


string

The string type supports UTF-8 encoded characters. Use "" for string literals. There are a number of supported escape sequences.

Escape SequenceName
\nnew line
\rcarriage return
\ttab
\bback space
\backslash
\"double quote
\'single quote
\x7FByte character code (2 hex digits)
\w7FFFWord character code (4 hex digits)

Examples

"abcdefghijklmnopqrstuvwxyz1234567890" (* valid *)
"Ͱऐቕ" (* valid *)
"🤓☝️" (* valid *)
"I love Halcyon\n It is awesome" (* valid *)
"I hate Halcyon\e It is not awesome" (* invalid *)

glyph

The character type. A glyph must contain only a single character or escape sequence. Use '' for glyph literals.


unit

A type used to represent nothing. Similar to void in C.


boolean

The boolean type is either true or false.

Functions


panic: () -> '0

Panic crashes the program intentionally. Since it returns '0, panic can be "returned" in any function without causing type issues.


assert: boolean -> ()

Crash the program if the parameter is false, otherwise do nothing and return unit.

Variations boolean -> boolean -> ()

Assert has several variations that have the same behavior. They crash if the condition is false, otherwise, they return unit.

FunctionCondition
assert_eqEqual
assert_neNot Equal
assert_geGreater or Equal
assert_leLess or Equal
assert_gtGreater
assert_ltLess

println: string -> ()

Prints the passed string to the console.

list

list is a type used to represent a linked list data structure. Every list is either Pair and contains two values (head, tail) or is Nil, and contains no values

<span class='hljs-keyword'>type</span> t = <span class='hljs-keyword'>fn</span> <span class='hljs-type'>I</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-punctuation'>(</span><span class='hljs-type'>Pair</span> <span class='hljs-type'>of</span> <span class='hljs-type'>I</span><span class='hljs-punctuation'>,</span> <span class='hljs-punctuation'>(</span><span class='hljs-type'>t</span> <span class='hljs-type'>I</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>)</span> | <span class='hljs-type'>Nil</span>

Functions


Nil: (list::t '0)

The constructor for an empty list item. This should only be located at the end of a list.

Example

<span class='hljs-keyword'>let</span> my_empty_list = <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span>Nil

Pair: ('0 * (list::t '0)) -> (list::t '0)

The constructor for a non-empty list item

Example

<span class='hljs-keyword'>let</span> my_list = <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Pair</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"item"</span><span class='hljs-punctuation'>,</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span>Nil<span class='hljs-punctuation'>)</span>

push: '0 -> (list::t '0) -> (list::t '0)

Creates a copy of the passed list with the passed element appended to the end.

Example

<span class='hljs-keyword'>let</span> my_list = <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Nil</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span>
<span class='hljs-comment'>(* my_list: Nil *)</span>
<span class='hljs-keyword'>let</span> my_new_list = <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-string'>"item"</span> my_list 
<span class='hljs-comment'>(* my_new_list: "item" &gt; Nil *)</span>

iterate: ('0 -> unit) -> (list::t '0) -> ()

Runs the passed operation on each element of the passed list, but doesn't create or return a new one.

Example

<span class='hljs-keyword'>let</span> my_list = <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span>Nil <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-string'>"Hello"</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-string'>" World!"</span>
<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>iterate</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span>println my_list
<span class='hljs-comment'>(* prints "Hello World!" *)</span>

map: ('0 -> '1) -> (list::t '0) -> (list::t '1)

Creates and returns a new list by applying the passed operation to each element in the passed list.

Example

<span class='hljs-keyword'>let</span> my_list = <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Nil</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-variable constant_'>3</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-variable constant_'>4</span> 
<span class='hljs-comment'>(* my_list: 3 &gt; 4 &gt; Nil *)</span>
<span class='hljs-keyword'>let</span> my_mapped_list = <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>map</span> <span class='hljs-punctuation'>(</span><span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-keyword'>=&gt;</span> a <span class='hljs-operator'>*</span> <span class='hljs-variable constant_'>2</span><span class='hljs-punctuation'>)</span> my_list
<span class='hljs-comment'>(* my_mapped_list: 6 &gt; 8 &gt; Nil *)</span>

length: (list::t '0) -> integer

Returns the length of the passed list.

Example

<span class='hljs-keyword'>let</span> length = <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span>Nil <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-variable constant_'>0</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-variable constant_'>1</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>length</span>
<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>format</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>integer</span> length <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span>
<span class='hljs-comment'>(* prints 2 *)</span>

nth: integer -> (list::t '0) -> '0

Returns the value of the passed list item at the position of the passed index.

Example

<span class='hljs-keyword'>let</span> my_list = <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span>Nil <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-string'>"one"</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-string'>"two"</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-string'>"three"</span>
<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>nth</span> <span class='hljs-variable constant_'>2</span> my_list <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span>
<span class='hljs-comment'>(* prints "two" *)</span>

concatenate: (list::t '0) -> (list::t '0) -> (list::t '0)

Adds the second passed list to the end of the first passed list.

Example

<span class='hljs-keyword'>let</span> my_list = <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span>Nil <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-string'>"one"</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-string'>"two"</span> 
<span class='hljs-keyword'>let</span> my_second_list = <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span>Nil <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-string'>"three"</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-string'>"four"</span> 
<span class='hljs-keyword'>let</span> my_final_list = <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>concatenate</span> my_list my_second_list
<span class='hljs-comment'>(* my_list: "one" &gt; "two" &gt; Nil *)</span>
<span class='hljs-comment'>(* my_second_list: "three" &gt; "four" &gt; Nil *)</span>
<span class='hljs-comment'>(* my_final_list: "one" &gt; "two" &gt; "three" &gt; "four" &gt; Nil*)</span>

fold: ('0 -> '1 -> '0) -> '0 -> (list::t '1) -> '0

Reduces the passed list to a single element using the passed function.

Example

<span class='hljs-keyword'>let</span> my_list = <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Nil</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-variable constant_'>1</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-variable constant_'>2</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>push</span> <span class='hljs-variable constant_'>3</span>
<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>list</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>fold</span> <span class='hljs-punctuation'>(</span><span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-params'>b</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-keyword'>if</span> a <span class='hljs-operator'>&lt;</span> b <span class='hljs-keyword'>then</span> a <span class='hljs-keyword'>else</span> b<span class='hljs-punctuation'>)</span> <span class='hljs-variable constant_'>10</span> my_list <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>format</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>integer</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span>
<span class='hljs-comment'>(* prints 1 *)</span>

opt

opt is a type that represents an optional value: every Option is either Some and contains a value, or None, and does not.

<span class='hljs-keyword'>type</span> t = <span class='hljs-keyword'>fn</span> <span class='hljs-type'>T</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-title function_'>Some</span> <span class='hljs-keyword'>of</span> <span class='hljs-type'>T</span> | <span class='hljs-title function_'>None</span>

Functions


Some: '0 -> (opt::t '0)

Constructor for a Some option.

Example

# <span class='hljs-keyword'>module</span> demo = 
    <span class='hljs-keyword'>let</span> my_some = <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Some</span> <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>12</span><span class='hljs-punctuation'>)</span>
# <span class='hljs-keyword'>end</span>

None: (opt::t '0)

Constructor for a None option.

Example

# <span class='hljs-keyword'>module</span> demo = 
    <span class='hljs-keyword'>let</span> my_none = <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>None</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span>
# <span class='hljs-keyword'>end</span>

is_some: (opt::t '0) -> boolean

Returns true if the passed option is Some, otherwise returns false.

Example

# <span class='hljs-keyword'>module</span> demo = 
    <span class='hljs-keyword'>let</span> value = <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Some</span> <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>12</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>is_some</span> 
    <span class='hljs-comment'>(* value is true *)</span>
# <span class='hljs-keyword'>end</span>

is_none: (opt::t '0) -> std:boolean

Returns true if the passed option is None, otherwise false.

Example

# <span class='hljs-keyword'>module</span> demo = 
    <span class='hljs-keyword'>let</span> value = <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>None</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>is_none</span> 
    <span class='hljs-comment'>(* value is true *)</span>
# <span class='hljs-keyword'>end</span>

unwrap: (opt::t '0) -> '0

If the passed option is a Some, returns the enclosed value, otherwise panics.

Example

# <span class='hljs-keyword'>module</span> demo = 
    <span class='hljs-keyword'>let</span> value = <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Some</span> <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>12</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>unwrap</span>
    <span class='hljs-comment'>(* value == 12 *)</span>
    <span class='hljs-keyword'>let</span> other_value = <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>None</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>unwrap</span>
    <span class='hljs-comment'>(* panics *)</span>
# <span class='hljs-keyword'>end</span>

map: ('0 -> '1) -> (opt::t '0) -> (opt::t '1)

If the passed option is a Some, returns a copy of the passed option with the passed function applied to its value. Otherwise, returns None.

Example

# <span class='hljs-keyword'>module</span> demo = 
    <span class='hljs-keyword'>let</span> my_opt = <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Some</span> <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>2</span><span class='hljs-punctuation'>)</span>
    <span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = my_opt <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>map</span> <span class='hljs-punctuation'>(</span><span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-keyword'>=&gt;</span> a <span class='hljs-operator'>*</span> <span class='hljs-variable constant_'>2</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>unwrap</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>from_integer</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print_string</span>
    <span class='hljs-comment'>(* prints 4 *)</span> 
# <span class='hljs-keyword'>end</span>

iterate: ('0 -> '1) -> (opt::t '0) -> ()

If the passed option is a Some, runs passed function on the passed option, then returns unit. Otherwise, returns unit.

Example

# <span class='hljs-keyword'>module</span> demo = 
    <span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Some</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Teto"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>opt</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>iterate</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span>print_string
    <span class='hljs-comment'>(* prints "Teto" *)</span>
# <span class='hljs-keyword'>end</span>

result

result is a type that represents either success (Ok) or failure (Error). Every result is either an Ok or an Error, both of which contain a value.

<span class='hljs-keyword'>type</span> result = <span class='hljs-keyword'>fn</span> <span class='hljs-type'>a</span> <span class='hljs-type'>b</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-title function_'>Ok</span> <span class='hljs-keyword'>of</span> <span class='hljs-type'>a</span> | <span class='hljs-title function_'>Error</span> <span class='hljs-keyword'>of</span> <span class='hljs-type'>b</span>

Functions


Ok: '0 -> (result::t '0 '1)

Constructor for an Ok result.

Example

<span class='hljs-keyword'>let</span> my_OK = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Ok</span> <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>2</span><span class='hljs-punctuation'>)</span>

Error: '1 -> (result::t '0 '1)

Constructor for an Error result.

Example

<span class='hljs-keyword'>let</span> my_Error = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Error</span> <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>2</span><span class='hljs-punctuation'>)</span>

is_ok: (result::t '0 '1) -> boolean

Returns true if the passed result is Ok, otherwise returns false.

Example

<span class='hljs-keyword'>let</span> my_result = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Ok</span> <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>2</span><span class='hljs-punctuation'>)</span>
<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = 
<span class='hljs-keyword'>if</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>is_ok</span> my_result <span class='hljs-keyword'>then</span>
    <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span> <span class='hljs-string'>"Ok!"</span>
<span class='hljs-keyword'>else</span>
    <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>println</span> <span class='hljs-string'>"Error!"</span>

<span class='hljs-comment'>(* prints "Ok!" *)</span>

is_err: (result::t '0 '1) -> boolean

Returns true if the passed result is Error, otherwise returns false.

Example

<span class='hljs-keyword'>let</span> my_result = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Error</span> <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>2</span><span class='hljs-punctuation'>)</span>
<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = 
<span class='hljs-keyword'>if</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>is_err</span> my_result <span class='hljs-keyword'>then</span>
    <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span> <span class='hljs-string'>"Error!"</span>
<span class='hljs-keyword'>else</span>
    <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span> <span class='hljs-string'>"Ok!"</span>

<span class='hljs-comment'>(* prints "Error!" *)</span>

unwrap_ok: (result::t '0 '1) -> '0

Returns the value contained in the passed Ok result. Panics if the result is Error.

Notes

It is recommended that you use pattern matching in most cases instead of this.

Example

<span class='hljs-keyword'>let</span> my_result = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Ok</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Hatsune Miku"</span><span class='hljs-punctuation'>)</span>
<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = my_result <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>unwrap_ok</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span>

<span class='hljs-comment'>(* prints "Hatsune Miku" *)</span>

unwrap_err: (result::t '0 '1) -> '1

Returns the value contained in the passed Error result. Panics if the result is Ok.

Notes

It is recommended that you use pattern matching in most cases instead of this.

Example

<span class='hljs-keyword'>let</span> my_result = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Error</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Kasane Teto"</span><span class='hljs-punctuation'>)</span>
<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = my_result <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>unwrap_err</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span>

<span class='hljs-comment'>(* prints "Kasane Teto" *)</span>

res_and: (result::t '0 '1) -> (result::t '0 '1) -> (result::t '0 '1)

If the first result passed is Ok, returns the second one. Otherwise, return the first result, which is an Error.

Example

<span class='hljs-keyword'>let</span> my_result = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Ok</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Akita Neru"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>res_and</span> Error<span class='hljs-punctuation'>(</span><span class='hljs-string'>"Hatsune Miku"</span><span class='hljs-punctuation'>)</span> 
<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-keyword'>match</span> my_result <span class='hljs-keyword'>with</span>
| result<span class='hljs-punctuation'>:</span><span class='hljs-type'>Ok</span> <span class='hljs-type'>of</span> <span class='hljs-type'>a</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span> a
| result<span class='hljs-punctuation'>:</span><span class='hljs-type'>Error</span> <span class='hljs-type'>of</span> <span class='hljs-type'>b</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span> b
<span class='hljs-comment'>(* prints "Hatsune Miku" *)</span>

<span class='hljs-keyword'>let</span> new_result = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Error</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Kasane Teto"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>res_and</span> Error<span class='hljs-punctuation'>(</span><span class='hljs-string'>"Hatsune Miku"</span><span class='hljs-punctuation'>)</span>
<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-keyword'>match</span> new_result <span class='hljs-keyword'>with</span>
| <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Ok</span> <span class='hljs-keyword'>of</span> a <span class='hljs-keyword'>=&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span> a
| <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Error</span> <span class='hljs-keyword'>of</span> b <span class='hljs-keyword'>=&gt;</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span> b
<span class='hljs-comment'>(* prints "Kasane Teto" *)</span>

expect: string -> (result::t '0 '1) -> '0

Returns the enclosed result value if the passed result is Ok. If the passed result is an Error, prints the passed string, then panics.

Example

<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Ok</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Akita Neru"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>expect</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Try doing it right next time"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span> 
<span class='hljs-comment'>(* prints "Akita Neru" *)</span>

<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Error</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Akita Neru"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>expect</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Try doing it right next time"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span> 
<span class='hljs-comment'>(* prints "Try doing it right next time", then panics *)</span>

res_or: (result::t '0 '1) -> (result::t '0 '1) -> (result::t '0 '1)

Returns the first passed result if it is Ok, otherwise returns the second passed result.

Example

<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Ok</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Akita Neru"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>res_or</span> Error <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Kasane Teto"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>unwrap_ok</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span> 
<span class='hljs-comment'>(* prints "Akita Neru" *)</span>

<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Error</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Akita Neru"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>res_or</span> Error <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Kasane Teto"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>unwrap_err</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span>
<span class='hljs-comment'>(* prints "Kasane Teto" *)</span>

<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Error</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Akita Neru"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>res_or</span> Ok <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Kasane Teto"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>unwrap_ok</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span>
<span class='hljs-comment'>(* prints "Kasane Teto" *)</span>

unwrap_or: (result::t '0 '1) -> '0 -> '0

Returns the value enclosed in the first passed result if its Ok, otherwise return the second passed value.

Example

<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Ok</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Hatsune Miku"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>unwrap_or</span> <span class='hljs-string'>"Kasane Teto"</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span> 
<span class='hljs-comment'>(* prints "Hatsune Miku" *)</span>

<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Error</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Hatsune Miku"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>unwrap_or</span> <span class='hljs-string'>"Kasane Teto"</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span> 
<span class='hljs-comment'>(* prints "Kasane Teto" *)</span>

and_then: (result::t '0 '1) -> ('0 -> '1) -> (result::t '0 '1)

If the passed result is Ok, returns a new result with an enclosed value equal to the passed result's enclosed value with the passed function appplied to it. Otherwise, returns the passed Error.

Example

<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Ok</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Kasane Teto"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>and_then</span> <span class='hljs-punctuation'>(</span><span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-keyword'>=&gt;</span> string<span class='hljs-punctuation'>:</span>concatenate a <span class='hljs-string'>" is my favorite"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>unwrap_ok</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span>
<span class='hljs-comment'>(* prints "Kasane Teto is my favorite" *)</span>

<span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Error</span> <span class='hljs-punctuation'>(</span><span class='hljs-string'>"Kasane Teto"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>and_then</span> <span class='hljs-punctuation'>(</span><span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-keyword'>=&gt;</span> string<span class='hljs-punctuation'>:</span>concatenate a <span class='hljs-string'>" is my favorite"</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>result</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>unwrap_err</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span>
<span class='hljs-comment'>(* prints "Kasane Teto" *)</span>

format

format is a module that provides functions for converting other types to strings.

Functions


integer: integer -> string

Returns the passed integer as a string.

Example

<span class='hljs-keyword'>do</span> <span class='hljs-title class_'>format</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>integer</span> <span class='hljs-variable constant_'>5</span>
    <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span>
<span class='hljs-comment'>(* prints "5" *)</span>

real: real -> string

Returns the passed real as a string.

Example

<span class='hljs-keyword'>do</span> <span class='hljs-title class_'>format</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>real</span> <span class='hljs-variable constant_'>5.4</span>
    <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span>
<span class='hljs-comment'>(* prints "5.4" *)</span>

boolean: boolean -> string

Returns the passed boolean as a string.

Example

<span class='hljs-keyword'>do</span> <span class='hljs-title class_'>format</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>boolean</span> <span class='hljs-built_in'>true</span>
    <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span>
<span class='hljs-comment'>(* prints "true" *)</span>

unit: unit -> string

Returns unit as a string.

Example

<span class='hljs-keyword'>do</span> <span class='hljs-title class_'>format</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>unit</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span>
    <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span>
<span class='hljs-comment'>(* prints "()" *)</span>

btree

btree is a type that represents a binary tree. Every btree is either a Node that contains a value and two children (Node or Nil), or it is Nil and contans no values.

<span class='hljs-keyword'>type</span> t = <span class='hljs-keyword'>fn</span> <span class='hljs-type'>I</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-punctuation'>(</span><span class='hljs-type'>Node</span> <span class='hljs-type'>of</span> <span class='hljs-type'>I</span><span class='hljs-punctuation'>,</span> <span class='hljs-punctuation'>(</span><span class='hljs-type'>t</span> <span class='hljs-type'>I</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>,</span> <span class='hljs-punctuation'>(</span><span class='hljs-type'>t</span> <span class='hljs-type'>I</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>)</span> | <span class='hljs-type'>Nil</span>

Functions


Nil: unit -> (btree '0)

The constructor for a Nil btree. This is used to represent an empty child.

Example

# <span class='hljs-keyword'>module</span> demo = 
  <span class='hljs-keyword'>let</span> my_empty_tree = <span class='hljs-title class_'>btree</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Nil</span><span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span>
# <span class='hljs-keyword'>end</span>

Node: '0 * btree '0 * btree '0 -> btree '0

The constructor for a Node btree.

Example

# <span class='hljs-keyword'>module</span> demo = 
  <span class='hljs-keyword'>let</span> my_tree = <span class='hljs-title function_'>btree</span><span class='hljs-punctuation'>:</span>Node <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>1</span><span class='hljs-punctuation'>,</span> <span class='hljs-title class_'>btree</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Nil</span><span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>,</span> <span class='hljs-title class_'>btree</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Nil</span><span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>)</span>
  <span class='hljs-comment'>(* my_tree ==  1
   *            / \
   *          nil nil
   *)</span>
# <span class='hljs-keyword'>end</span>

insert: '0 -> ('0 -> '0 -> boolean) -> (btree '0) -> (btree '0)

Returns a copy of the passed tree with the passed value inserted according to the passed operation.

Notes

insert checks if the function is true with the passed value and the current tree value, if it is, it will attempt to insert the passed value as the left child. Otherwise, it will attempt to insert the passed value as the right child. This process is repeateded recursively until a Node has a Nil child in the appropriate position.

Example

# <span class='hljs-keyword'>module</span> demo = 
  <span class='hljs-keyword'>let</span> my_tree = <span class='hljs-title function_'>btree</span><span class='hljs-punctuation'>:</span>Node <span class='hljs-punctuation'>(</span><span class='hljs-variable constant_'>5</span><span class='hljs-punctuation'>,</span> <span class='hljs-title class_'>btree</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Nil</span><span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>,</span> <span class='hljs-title class_'>btree</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Nil</span><span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span><span class='hljs-punctuation'>)</span>
  <span class='hljs-keyword'>let</span> my_new_tree = <span class='hljs-title function_'>btree</span><span class='hljs-punctuation'>:</span>insert <span class='hljs-variable constant_'>2</span> <span class='hljs-punctuation'>(</span><span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-params'>b</span> <span class='hljs-keyword'>=&gt;</span> a <span class='hljs-operator'>&lt;</span> b<span class='hljs-punctuation'>)</span> my_tree
  <span class='hljs-comment'>(* my_new_tree == 5
  *                / \
  *               2  
  *)</span>
  <span class='hljs-keyword'>let</span> my_newer_tree = <span class='hljs-title function_'>btree</span><span class='hljs-punctuation'>:</span>insert <span class='hljs-variable constant_'>7</span> <span class='hljs-punctuation'>(</span><span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-params'>b</span> <span class='hljs-keyword'>=&gt;</span> a <span class='hljs-operator'>&lt;</span> b<span class='hljs-punctuation'>)</span> my_new_tree
  <span class='hljs-comment'>(* my_newer_tree == 5
  *                  / \
  *                 2   7 
  *                / \ / \ 
  *)</span>
  <span class='hljs-keyword'>let</span> my_newest_tree = <span class='hljs-title function_'>btree</span><span class='hljs-punctuation'>:</span>insert <span class='hljs-variable constant_'>9</span> <span class='hljs-punctuation'>(</span><span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-params'>b</span> <span class='hljs-keyword'>=&gt;</span> a <span class='hljs-operator'>&lt;</span> b<span class='hljs-punctuation'>)</span> my_newer_tree
  <span class='hljs-comment'>(* my_newest_tree == 5
  *                   / \
  *                  2   7 
  *                 / \ / \
  *                        9
  *)</span>
# <span class='hljs-keyword'>end</span>

iterate_tree_df: ('0 -> unit) -> (btree '0) -> unit

Runs the passed function on each element in the tree depth-first, then returns unit.

Example

# <span class='hljs-keyword'>module</span> demo = 
  <span class='hljs-keyword'>let</span> lt = <span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-params'>b</span> <span class='hljs-keyword'>=&gt;</span> a <span class='hljs-operator'>&lt;</span> b  
  <span class='hljs-keyword'>let</span> my_tree = <span class='hljs-title class_'>btree</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Nil</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>5</span> lt <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>2</span> lt <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>7</span> lt <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>8</span> lt <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>3</span> lt <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>1</span> lt
  <span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>btree</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>iterate_tree_df</span> <span class='hljs-punctuation'>(</span><span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-keyword'>=&gt;</span> string<span class='hljs-punctuation'>:</span>from_int <span class='hljs-operator'>|&gt;</span> <span class='hljs-title function_'>std</span><span class='hljs-punctuation'>:</span>print_string<span class='hljs-punctuation'>)</span> my_tree
  <span class='hljs-comment'>(* my_tree == 5
  *            / \
  *           2   7 
  *          / \ / \
  *         1  3    8 
  *)</span>
  <span class='hljs-comment'>(* prints 123578 *)</span>
# <span class='hljs-keyword'>end</span>

iterate_tree_bf: ('0 -> unit) -> (btree '0) -> unit

Runs the passed function on each element in the tree breadth-first, then returns unit.

Example

# <span class='hljs-keyword'>module</span> demo = 
  <span class='hljs-keyword'>let</span> lt = <span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-params'>b</span> <span class='hljs-keyword'>=&gt;</span> a <span class='hljs-operator'>&lt;</span> b  
  <span class='hljs-keyword'>let</span> my_tree = <span class='hljs-title class_'>btree</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Nil</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>5</span> lt <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>2</span> lt <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>7</span> lt <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>8</span> lt <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>3</span> lt <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>1</span> lt
  <span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>btree</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>iterate_tree_bf</span> <span class='hljs-punctuation'>(</span><span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-keyword'>=&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span>from_int <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>std</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print_string</span><span class='hljs-punctuation'>)</span> my_tree
  <span class='hljs-comment'>(* my_tree == 5
  *            / \
  *           2   7 
  *          / \ / \
  *         1  3    8 
  *)</span>
  <span class='hljs-comment'>(* prints 521378 *)</span>
# <span class='hljs-keyword'>end</span>

map_tree: ('0 -> '1) -> (btree '0) -> (btree '1)

Returns a copy of the passed tree with the passed function applied to each element.

Examples

# <span class='hljs-keyword'>module</span> demo = 
  <span class='hljs-keyword'>let</span> lt = <span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-params'>b</span> <span class='hljs-keyword'>=&gt;</span> a <span class='hljs-operator'>&lt;</span> b  
  <span class='hljs-keyword'>let</span> my_tree = <span class='hljs-title class_'>btree</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>Nil</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>5</span> lt <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>2</span> lt <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>7</span> lt <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>8</span> lt <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>3</span> lt <span class='hljs-operator'>|&gt;</span> <span class='hljs-variable constant_'>1</span> lt
  <span class='hljs-comment'>(* my_tree == 5
  *            / \
  *           2   7 
  *         / \ / \
  *        1  3    8 
  *)</span>
  <span class='hljs-keyword'>let</span> my_mapped_tree = <span class='hljs-title function_'>btree</span><span class='hljs-punctuation'>:</span>map_tree <span class='hljs-punctuation'>(</span><span class='hljs-keyword'>fn</span> <span class='hljs-params'>a</span> <span class='hljs-keyword'>=&gt;</span> a <span class='hljs-operator'>*</span> <span class='hljs-variable constant_'>2</span><span class='hljs-punctuation'>)</span> my_tree
  <span class='hljs-comment'>(* my_mapped_tree == 10
  *                    / \
  *                   4   14 
  *                  / \ / \
  *                 2  6    16 
  *)</span>
# <span class='hljs-keyword'>end</span>

string

string is a module that provides functions for operating on strings

Functions


Prints the passed string to the console.

Example

# <span class='hljs-keyword'>module</span> demo = 
    <span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span> <span class='hljs-string'>"Hi"</span>
    <span class='hljs-comment'>(* Prints "Hi" *)</span>
# <span class='hljs-keyword'>end</span>

length: string -> integer

Returns the length of the passed string.

Example

# <span class='hljs-keyword'>module</span> demo = 
    <span class='hljs-keyword'>let</span> my_int = <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>length</span> <span class='hljs-string'>"Hello"</span>
    <span class='hljs-comment'>(* my_int == 5 *)</span>
# <span class='hljs-keyword'>end</span>

concatenate: string -> string -> string

Adds the second string to the end of the first.

Example

# <span class='hljs-keyword'>module</span> demo = 
    <span class='hljs-keyword'>let</span> <span class='hljs-punctuation'>(</span><span class='hljs-punctuation'>)</span> = <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>concatenate</span> <span class='hljs-string'>"Kasane"</span> <span class='hljs-string'>" Teto"</span> <span class='hljs-operator'>|&gt;</span> <span class='hljs-title class_'>string</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>print</span>
    <span class='hljs-comment'>(* prints "Kasane Teto" *)</span>
# <span class='hljs-keyword'>end</span>

integer

integer is a module that provides functions for operating on integers.

Functions


abs: integer -> integer

Returns the absolute value of the passed integer.

Example

# <span class='hljs-keyword'>module</span> demo =
    <span class='hljs-keyword'>let</span> five = <span class='hljs-title class_'>integer</span><span class='hljs-punctuation'>::</span>abs <span class='hljs-operator'>-</span><span class='hljs-variable constant_'>5</span>
    <span class='hljs-keyword'>let</span> alsofive = <span class='hljs-title class_'>integer</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>abs</span> <span class='hljs-variable constant_'>5</span>
# <span class='hljs-keyword'>end</span>

pow: integer -> integer -> integer

Returns the first passed integer to the power of the second passed integer.

Example

# <span class='hljs-keyword'>module</span> demo =
    <span class='hljs-keyword'>let</span> four = <span class='hljs-title class_'>integer</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>pow</span> <span class='hljs-variable constant_'>2</span> <span class='hljs-variable constant_'>2</span>
    <span class='hljs-keyword'>let</span> eight = <span class='hljs-title class_'>integer</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>pow</span> <span class='hljs-variable constant_'>2</span> <span class='hljs-variable constant_'>3</span>
# <span class='hljs-keyword'>end</span>

real

real is a module that provides functions for operating on reals.

Functions


abs: real -> real

Returns the absolute value of the passed real.

Example

<span class='hljs-keyword'>let</span> fourpointfive = <span class='hljs-title class_'>real</span><span class='hljs-punctuation'>::</span>abs <span class='hljs-operator'>-</span><span class='hljs-variable constant_'>4.5</span>
<span class='hljs-keyword'>let</span> alsofourpointfive = <span class='hljs-title class_'>real</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>abs</span> <span class='hljs-variable constant_'>4.5</span>

truncate: real -> real

Truncates the passed real by removing the decimal component.

Example

<span class='hljs-keyword'>let</span> four = <span class='hljs-title class_'>real</span><span class='hljs-punctuation'>::</span><span class='hljs-title function_'>truncate</span> <span class='hljs-variable constant_'>4.5</span>

Appendix

The following sections contain reference material that may make your development experience more halcyon.

Halcyon

  1. calm; peaceful; tranquil.
  2. happy; blissful; carefree.
  3. prosperous; wealthy.

Appendix A: Keywords

The following list contains keywords that are reserved for current or future use by the Halcyon language. As such, they cannot be used as identifiers.

Keywords Currently in Use

The following is a list of keywords currently in use, with their functionality described.

KeywordUseExample
module, endDeclares the beginning and end of a module respectivelymodule demo = ... end
importImports a function from another language, such as JavaScript or C
letDefines a variablelet myint = 5
doExecutes an expression (like a main function)do string::print "Hi"
typeDefines a new type, or type aliastype twoints = (std::int, std::int)
match, withMatches a discriminant with one or more patternsmatch myint with |4 => ... |5 => ...
if,then,elseEvaluates to a value based on a boolean expressionif myint == 5 then ... else ...
fnDeclares a functionlet myfn = fn a => a + 1
ofDenotes types that a constructor name containstype result = fn A B => Ok of A | Error of B
inLimits a variable's scope to the next expressionlet myint = 5 in let mynewint = myint + 1

Appendix B: Operators and Symbols

This appendix contains a glossary of Halcyon's syntax, including operators and other symbols.

Operators

SymbolDescription
(unary) - -.arithmetic negation
(unary) notlogical negation
* *.multiplication
/ /.division
%modulus
+ +.addition
- -.subtraction
(function call)
>> <<function composition
xorlogical XOR
orlogical OR
|>function pipe
== != <= >= < >comparison
andlogical AND
;

Non-operator Symbols

The following list contains all symbols that don’t function as operators; that is, they don’t behave like a function.

SymbolDescription
ident : typeType constraint
()Unit literal/Empty tuple
ident : ()Alias for std::unit
(expr,)Single element tuple
(expr, ...)Tuple expression
(type,...)Tuple type
[type]Array type
[expr, ...]Array literal
ident::identModule path
ident = exprAssignment
{ident,...}Struct type
{expr,...}Struct literal
ident.identStruct field access
pat | patPattern alternatives
type | typeSum type alternatives
pat => exprPart of match arm syntax
signature => exprPart of function syntax
_Wildcard pattern match
_“Ignored” pattern binding
--Line comment
(*...*)Block Comment