Prelude

The Prelude is FreeST’s standard library. It is imported by default into every module, so all the types and functions on this page are in scope without any import.

Terse operator families are collected into tables; everything else has its own entry with its signature and — where the library documents it — a description and a worked example. Sections and their order mirror the Prelude’s own source file.

Table of contents

undefined

undefined : forall (a : *T) -> a

An inhabitant of every unrestricted type. Used as the placeholder implementation for every other builtin in this file — useful when writing your own builtins, but this one ought to be a builtin itself.

error

error : forall (a : 1T) -> String -> a

Aborts the program, printing the given message.

Basic datatypes

Bool

type Bool : *T
data Bool = True | False

Boolean operators

Function Type
(||) Bool -> Bool -> Bool
(&&) Bool -> Bool -> Bool

not

not : Bool -> Bool

Boolean complement.

otherwise

otherwise : Bool

Always True. Handy as the last guard of a definition.

Maybe

type Maybe : *T -> *T
data Maybe a = Nothing | Just a

maybe

maybe : forall (a : *T) (b : *T) -> b -> (a -> b) -> Maybe a -> b

Consumes a Maybe: returns the given default on Nothing, or applies the function to the contents on Just.

Either

type Either : *T -> *T -> *T
data Either a b = Left a | Right b

either

either : forall (a : *T) (b : *T) (c : 1T) -> (a -> c) -> (b -> c) -> Either a b -> c

Consumes an Either: applies the first function to a Left, the second to a Right.

Character conversions

Function Type
ord Char -> Int
chr Int -> Char

String

type String : *T
type String = [Char]

show

show : forall (a : *T) -> a -> String

Renders a value as a String.

Tuples

fst

fst : forall (a : 1T) (b : *T) -> (a, b) -> a

Extracts the first element from a pair, discarding the second.

snd

snd : forall (a : *T) (b : 1T) -> (a, b) -> b

Extracts the second element from a pair, discarding the first.

swap

swap : forall (a : 1T) (b : 1T) -> (a, b) -> (b, a)

Swaps the components of a pair. The expression swap (1, True) evaluates to (True, 1).

curry

curry : forall (a : *T) (b : 1T) (c : 1T) -> ((a, b) -> c) -> a -> b -> c

Converts a function that receives a pair into a function that receives its arguments one at a time.

uncurry

uncurry : forall (a : 1T) (b : 1T) (c : 1T) -> (a -> b -> c) -> ((a, b) -> c)

Converts a function that receives its arguments one at a time into a function on pairs.

Comparison

Only Int and Float are comparable, for now.

Function Type
(<) Int -> Int -> Bool
(<=) Int -> Int -> Bool
(==) Int -> Int -> Bool
(>=) Int -> Int -> Bool
(>) Int -> Int -> Bool
(/=) Int -> Int -> Bool
(>.) Float -> Float -> Bool
(<.) Float -> Float -> Bool
(>=.) Float -> Float -> Bool
(<=.) Float -> Float -> Bool

Numeric functions

Int

Function Type
(+) Int -> Int -> Int
(-) Int -> Int -> Int
(*) Int -> Int -> Int
(/) Int -> Int -> Int
(^) Int -> Int -> Int
subtract Int -> Int -> Int
quot Int -> Int -> Int
rem Int -> Int -> Int
div Int -> Int -> Int
mod Int -> Int -> Int
min Int -> Int -> Int
max Int -> Int -> Int
gcd Int -> Int -> Int
lcm Int -> Int -> Int
succ Int -> Int
pred Int -> Int
abs Int -> Int
negate Int -> Int
even Int -> Bool
odd Int -> Bool

Float

Function Type
(+.) Float -> Float -> Float
(-.) Float -> Float -> Float
(*.) Float -> Float -> Float
(/.) Float -> Float -> Float
(**) Float -> Float -> Float
maxF Float -> Float -> Float
minF Float -> Float -> Float
logBase Float -> Float -> Float
absF Float -> Float
negateF Float -> Float
recip Float -> Float
exp Float -> Float
log Float -> Float
sqrt Float -> Float
log1p Float -> Float
expm1 Float -> Float
log1pexp Float -> Float
log1mexp Float -> Float
sin Float -> Float
cos Float -> Float
tan Float -> Float
asin Float -> Float
acos Float -> Float
atan Float -> Float
sinh Float -> Float
cosh Float -> Float
tanh Float -> Float
truncate Float -> Int
round Float -> Int
ceiling Float -> Int
floor Float -> Int
pi Float
fromInteger Int -> Float

Miscellaneous functions

id

id : forall (a : 1T) -> a -> a

The identity function. Returns the exact same value.

id 5       -- 5
id "Hello" -- "Hello"

const

const : forall (a : *T) (b : *T) -> a -> b -> a

Returns its first argument and ignores its second.

(.)

(.) : forall #m #n (a : 1T) (b : 1T) (c : 1T) -> (b -m-> c) -> (a -n-> b) -m-> a -m+n-> c

Function composition: (f . g) x is f (g x).

flip

flip : forall #m #n #o (a : 1T) (b : m T) (c : 1T) -> (a -n-> b -o-> c) -> b -n-> a -m+n-> c

Swaps the order of the first two parameters of a function.

($)

($) : forall #m (a : 1T) (b : 1T) -> (a -m-> b) -> a -m-> b

Application operator. Takes a function and an argument, and applies the first to the latter. This operator has low right-associative binding precedence, allowing parentheses to be omitted in certain situations. For example:

f $ g $ h x = f (g (h x))

(|>)

(|>) : forall #m #n (a : m T) (b : 1T) -> a -> (a -n-> b) -m-> b

Reverse application operator. Provides notational convenience, especially when chaining channel operations. For example:

f : !Int ; !Bool ; Close -> ()
f c = c |> send 5 |> send True |> close

until

until : forall (a : *T) -> (a -> Bool) -> (a -> a) -> a -> a

Applies the function passed as the second argument to the third one and uses the predicate in the first argument to evaluate the result: if it comes as True it returns it, otherwise it continues to apply the function on previous results until the predicate evaluates to True.

-- | First base 2 power greater than a given limit
firstPowerGreaterThan : Int -> Int
firstPowerGreaterThan limit = until @Int (> limit) (*2) 1

(;)

(;) : forall (a : *T) (b : 1T) -> a -> b -> b

Sequential composition. Takes two expressions, evaluates the former and discards the result, then evaluates the latter. For example, 3 ; 4 evaluates to 4.

fix

fix : forall (a : *T) -> ((a -> a) -> (a -> a)) -> (a -> a)

Fixed-point Z combinator.

Lists

null

null : forall a -> [a] -> Bool

True on the empty list, False otherwise.

(++)

(++) : forall (a : *T) -> [a] -> [a] -> [a]

Appends two (unrestricted) lists.

head : forall (a : *T) -> [a] -> a

The first element of a list. Errors on the empty list.

last

last : forall (a : *T) -> [a] -> a

The last element of a list. Errors on the empty list.

tail

tail : forall (a : *T) -> [a] -> [a]

Every element of a list except the first. Errors on the empty list.

init

init : forall (a : *T) -> [a] -> [a]

Every element of a list except the last. Errors on the empty list.

length

length : forall (a : *T) -> [a] -> Int

The number of elements in a list.

sum

sum : [Int] -> Int

The sum of a list of integers.

reverse

reverse : forall (a : *T) -> [a] -> [a]

Reverses a list. Uses an accumulator internally so it runs in linear time.

map

map : forall (a : *T) (b : *T) -> (a -> b) -> [a] -> [b]

Applies a function to every element of a list, producing a new list.

foldl

foldl : forall #m #n (a : m T) (b : *T) -> (a -> b -n-> a) -> a -> [b] -m-> a

Left fold: combines the elements of a list with an accumulator function, starting from an initial value and processing the list left to right.

foldr

foldr : forall #m #n (a : *T) (b : m T) -> (a -> b -n-> b) -> b -> [a] -m-> b

Right fold: combines the elements of a list with an accumulator function, processing the list right to left.

takeWhile

takeWhile : forall (a : *T) -> (a -> Bool) -> [a] -> [a]

The longest prefix of a list all of whose elements satisfy the predicate.

dropWhile

dropWhile : forall (a : *T) -> (a -> Bool) -> [a] -> [a]

Drops the longest prefix of a list all of whose elements satisfy the predicate, and returns the rest.

span

span : forall (a : *T) -> (a -> Bool) -> [a] -> ([a], [a])

Splits a list into the longest prefix satisfying the predicate and the remaining suffix. Equivalent to (takeWhile p xs, dropWhile p xs).

intercalate

intercalate : forall (a : *T) -> [a] -> [[a]] -> [a]

Joins a list of lists with a separator, e.g. intercalate ", " ["a", "b"] is "a, b".

Linear lists

Alongside the unrestricted list type [a] (built with [] and ::), the Prelude also has a linear list type, written [a]' and built with []' and ::'. A linear list can hold linear elements, and — like every linear value — must be consumed exactly once. The combinators below mirror their unrestricted counterparts.

Function Type
(++') forall (a : 1T) -> [a]' -> [a]' -1-> [a]'
map' forall (a : 1T) (b : 1T) -> (a -> b) -> [a]' -> [b]'
foldl' forall #m #n (a : m T) (b : 1T) -> (a -> b -n-> a) -> a -> [b]' -m-> a
foldr' forall #m #n (a : 1T) (b : m T) -> (a -> b -n-> b) -> b -> [a]' -m-> b

mapUL / mapLU

mapUL : forall (a : *T) (b : 1T) -> (a -> b) -> [a] -> [b]'
mapLU : forall (a : 1T) (b : *T) -> (a -> b) -> [a]' -> [b]

Convert between the unrestricted and linear list types while mapping a function over the elements: mapUL turns an unrestricted list into a linear one, mapLU turns a linear list into an unrestricted one.

Strings

isSpace

isSpace : Char -> Bool

True for a space or any of the whitespace control characters (tab, newline, carriage return, …).

words

words : String -> [String]

Splits a string into a list of whitespace-separated words.

unwords

unwords : [String] -> String

Joins a list of words back into a single string, separated by single spaces. The inverse of words (modulo how repeated whitespace is collapsed).

Errors

Function Type
undefined forall (a : *T) -> a
error forall (a : 1T) -> String -> a

Concurrency

fork

fork : forall #m (a : *T) -> (() -m-> a) -> ()

Spawns a thunk as a new thread. The thunk’s return value, of unrestricted base kind, is discarded.

send

send : forall #m (a : m T) -> a -> forall (b : 1S) -> !a;b -m-> b

Sends a value on a channel. Returns the continuation channel.

receive

receive : forall (a : 1T) (b : 1S) -> ?a;b -> (a, b)

Receives a value on a channel. Returns the received value and the continuation channel.

wait

wait : Wait -> ()

Waits for a channel to be closed.

close

close : Close -> ()

Closes a channel.

sendAndWait

sendAndWait : forall #m (a : m T) -> a -> !a ; Wait -m-> ()

Sends a value on a given channel and then waits for the channel to be closed. Returns ().

sendAndClose

sendAndClose : forall #m (a : m T) -> a -> !a ; Close -m-> ()

Sends a value on a given channel and then closes the channel. Returns ().

receiveAndWait

receiveAndWait : forall (a : 1T) -> ?a ; Wait -> a

Receives a value from a channel that continues to Wait, waits for the continuation and returns the value.

_ =
  -- create channel endpoints
  let (c, s) = channel @(?String ; Wait) in
  -- fork a thread that prints the received value
  fork (\_ -1-> c |> receiveAndWait @String |> putStrLn);
  -- send a string through the channel (and wait for its endpoint to close)
  s |> send "Hello!" |> close

receiveAndClose

receiveAndClose : forall (a : 1T) -> ?a ; Close -> a

As in receiveAndWait, only that the continuation is Close and the function closes the channel rather than waiting for it to close.

send_

send_ : forall #m (a : m T) -> a -> *!a -m-> *!a

Sends a value on an unrestricted (shared) channel. Unrestricted version of send. Returns the (unrestricted) channel, so further operations can be chained.

receive_

receive_ : forall (a : 1T) -> *?a -> a

Receives a value from an unrestricted channel. Unrestricted version of receive. The channel need not be returned: it can be reused as often as needed.

accept

accept : forall (a : 1C) -> *!a -> Dual a

Session initiation. Accepts a request for a linear session on a shared channel. The requester uses a receive_ operation to obtain the channel end.

forkWith

forkWith : forall #m (a : 1C) (b : *T) -> (Dual a -m-> b) -> a

Creates a new child process and a channel through which it can communicate with its parent process. Returns the channel endpoint. The forked function’s return value, of unrestricted base kind, is discarded.

_ =
  -- fork a thread that receives a string and prints it
  let c = forkWith @(!String ; Wait) (\s -1-> s |> receiveAndClose @String |> putStrLn) in
  -- send the string to be printed
  c |> send "Hello!" |> wait

runServer

runServer : forall (a : *T) (b : 1C) -> (a -> Dual b -> a) -> a -> *!b -> Void @*T

Runs an infinite shared server, given a function to handle one client session, an initial state, and the server’s shared channel endpoint. It behaves as an infinite sequential application of the handler function over newly accepted sessions, threading the state through each call. Since it never returns, its result type is Void @*T.

Note: this only works with session types that use session initiation.

type SharedCounter = *?Counter
type Counter = +{ Inc: Close
                , Dec: Close
                , Get: ?Int ; Close
                }

-- | Handler for a counter
counterService : Int -> Dual Counter -> Int
counterService i (&Inc c) = wait c ; i + 1
counterService i (&Dec c) = wait c ; i - 1
counterService i (&Get c) = c |> send i |> wait ; i

-- | Counter server
runCounterServer : Dual SharedCounter -> Void @*T
runCounterServer = runServer @Int @Counter counterService 0

times

times : forall (a : *T) -> Int -> (() -> a) -> ()

Executes a thunk n times, sequentially.

_ =
  -- print "Hello!" 5 times sequentially
  times @() 5 (\_ -> putStrLn "Hello!")

parallel

parallel : forall (a : *T) -> Int -> (() -> a) -> ()

Forks n identical threads. Works the same as a times call, but in parallel instead of sequentially.

_ =
  -- print "Hello!" 5 times in parallel
  parallel 5 (\_ -> putStrLn "Hello!")

Fork-join

ForkJoin

type ForkJoin = *+{Over}

A simple channel-based fork-join coordination protocol: each child thread signals completion by selecting the Over branch, and the parent thread waits for a fixed number of such completions.

join

join : ForkJoin -> ()

Signals completion of a child thread to the parent waiting on the join channel.

await

await : Int -> Dual ForkJoin -> ()

Waits until n child threads have signalled completion through the join channel.

_ =
  let (w, r) = channel @ForkJoin in
  fork (\_ -> putChar 'A'; join w) ;
  fork (\_ -> putChar 'B'; join w) ;
  fork (\_ -> putChar 'C'; join w) ;
  await 3 r

I/O

I/O streams

Input stream

InStream

type InStream : 1C
type InStream = +{ GetChar : ?Char   ; InStream
                 , GetLine : ?String ; InStream
                 , IsEOF   : ?Bool   ; InStream
                 , Stop    : Wait
                 }

The InStream type describes input streams (such as stdin and read files). GetChar reads a single character, GetLine reads a line, and IsEOF checks for the EOF (End-Of-File) token, i.e., if an input stream has reached the end. Operations on this channel terminate with the Stop option.

hGenericGet

hGenericGet : forall (a : *T) -> (InStream -> ?a; InStream) -> InStream -> (a, InStream)

Reads a value selected from an InStream by a selector (e.g. select GetChar), returning the value and the continuation channel endpoint. This is how hGetChar, hGetLine and hIsEOF are themselves defined, e.g. hGetChar = hGenericGet (select GetChar).

hGetChar

hGetChar : InStream -> (Char, InStream)

Reads a character from an InStream channel endpoint. Behaves as |> select GetChar |> receive.

hGetLine

hGetLine : InStream -> (String, InStream)

Reads a line (as a string) from an InStream channel endpoint. Behaves as |> select GetLine |> receive.

hIsEOF

hIsEOF : InStream -> (Bool, InStream)

Checks if an InStream reached the EOF token that marks where no more input can be read. Behaves as |> select IsEOF |> receive.

hGetContent

hGetContent : InStream -> (String, InStream)

Reads an InStream channel endpoint all the way to EOF, separating lines with the newline character \n, and returns the accumulated content together with the (now exhausted) continuation channel.

hCloseIn

hCloseIn : InStream -> ()

Closes an InStream channel endpoint. Behaves as |> select Stop |> wait.

hGenericGet_

hGenericGet_ : forall (a : *T) -> (InStream -> (a, InStream)) -> *?InStream -> a

The unrestricted version of an InStream getter: receives the InStream channel endpoint (via session initiation), runs the getter, closes the endpoint with hCloseIn, and returns the value. This is how hGetChar_ and hGetLine_ are themselves defined, e.g. hGetChar_ = hGenericGet_ hGetChar.

hGetChar_

hGetChar_ : *?InStream -> Char

Unrestricted version of hGetChar. Behaves the same, except it first receives an InStream channel endpoint (via session initiation), executes an hGetChar and then closes the endpoint with hCloseIn.

hGetLine_

hGetLine_ : *?InStream -> String

Unrestricted version of hGetLine. Behaves the same, except it first receives an InStream channel endpoint (via session initiation), executes an hGetLine and then closes the endpoint with hCloseIn.

Output stream

OutStream

type OutStream : 1C
type OutStream = +{ PutStr   : !String ; OutStream
                  , PutStrLn : !String ; OutStream
                  , Stop     : Wait
                  }

The OutStream type describes output streams (such as stdout, stderr and write mode files). PutStr outputs a string, and PutStrLn outputs a string followed by the newline character (\n). Operations on this channel must end with the Stop option.

hGenericPut

hGenericPut : forall (a : *T) -> (OutStream -> !a; OutStream) -> a -> OutStream -> OutStream

Writes a value on an OutStream through a selector (e.g. select PutStr), returning the continuation channel endpoint. This is how hPutStr and hPutStrLn are themselves defined, e.g. hPutStr = hGenericPut (select PutStr).

hPutStr

hPutStr : String -> OutStream -> OutStream

Writes a string on an OutStream channel endpoint. Behaves as |> select PutStr |> send.

hPutStrLn

hPutStrLn : String -> OutStream -> OutStream

Writes a string on an OutStream channel endpoint, followed by the newline character. Behaves as |> select PutStrLn |> send.

hPutChar

hPutChar : Char -> OutStream -> OutStream

Writes a character on an OutStream channel endpoint. There is no dedicated protocol branch for single characters: this is implemented as hPutStr [c], sending the character as a one-character string.

hPrint

hPrint : forall (a : *T) -> a -> OutStream -> OutStream

Writes the string representation of a value on an OutStream channel endpoint, followed by the newline character. Behaves as hPutStrLn . show.

hCloseOut

hCloseOut : OutStream -> ()

Closes an OutStream channel endpoint. Behaves as |> select Stop |> wait.

hGenericPut_

hGenericPut_ : forall (a : *T) -> (a -> OutStream -> OutStream) -> a -> *?OutStream -> ()

The unrestricted version of an OutStream putter: receives the OutStream channel endpoint (via session initiation), runs the putter, and closes the endpoint with hCloseOut. This is how hPutChar_, hPutStr_, hPutStrLn_ and hPrint_ are themselves defined, e.g. hPutChar_ = hGenericPut_ hPutChar.

hPutChar_

hPutChar_ : Char -> *?OutStream -> ()

Unrestricted version of hPutChar. Behaves the same, except it first receives an OutStream channel endpoint (via session initiation), executes an hPutChar and then closes the endpoint with hCloseOut.

hPutStr_

hPutStr_ : String -> *?OutStream -> ()

Unrestricted version of hPutStr. Behaves similarly, except that it first receives an OutStream channel endpoint (via session initiation), executes an hPutStr and then closes the endpoint with hCloseOut.

hPutStrLn_

hPutStrLn_ : String -> *?OutStream -> ()

Unrestricted version of hPutStrLn. Behaves similarly, except that it first receives an OutStream channel endpoint (via session initiation), executes an hPutStrLn and then closes the endpoint with hCloseOut.

hPrint_

hPrint_ : forall (a : *T) -> a -> *?OutStream -> ()

Unrestricted version of hPrint. Behaves similarly, except that it first receives an OutStream channel endpoint (via session initiation), executes an hPrint and then closes the endpoint with hCloseOut.

Standard I/O

stdin

Function Type Description
stdin *?InStream Standard input stream. Reads from the console.
getChar () -> Char Reads a single character from stdin.
getLine () -> String Reads a single line from stdin.

stdout and stderr

Function Type Description
stdout *?OutStream Standard output stream. Prints to the console, via the h*_ functions (e.g. hPutStrLn_ s stdout) or the put* wrappers below.
stderr *?OutStream Standard error stream. Prints to the console, via the h*_ functions (e.g. hPutStrLn_ s stderr); unlike stdout, it has no dedicated put* wrappers.
putChar Char -> () Prints a character to stdout. Behaves the same as hPutChar_ c stdout, where c is the character to be printed.
putStr String -> () Prints a string to stdout. Behaves the same as hPutStr_ s stdout, where s is the string to be printed.
putStrLn String -> () Prints a string to stdout, followed by the newline character \n. Behaves as hPutStrLn_ s stdout, where s is the string to be printed.
print forall (U : *T) -> U -> () Prints the string representation of a given value to stdout, followed by the newline character \n. Behaves the same as hPrint_ @U v stdout, where v is the value to be printed and U its type.

Files

FreeST models files as streams: reading opens an InStream, writing or appending opens an OutStream. Opening currently raises an error on failure rather than returning a Maybe, since a total variant would need a linear Maybe (Maybe is *T -> *T, but the streams are 1C) — that is not yet available.

FilePath

type FilePath : *T
type FilePath = String

openReadFile

openReadFile : FilePath -> InStream

Opens a file for reading. The file is closed when the stream is.

openWriteFile

openWriteFile : FilePath -> OutStream

Opens a file for writing, discarding its current content.

openAppendFile

openAppendFile : FilePath -> OutStream

Opens a file for writing, after its current content.

readFile

readFile : FilePath -> String

The entire content of a file, separating lines with \n. Behaves as openReadFile followed by hGetContent and hCloseIn.

writeFile

writeFile : FilePath -> String -> ()

Writes a string to a file, discarding its current content.

appendFile

appendFile : FilePath -> String -> ()

Writes a string to a file, after its current content.

Command line

Function Type Description
getArgs () -> [String] The arguments the program was run with, excluding the program name.
getProgName () -> String The name the program was run under.

Environment

lookupEnv

lookupEnv : String -> Maybe String

The value of an environment variable, if it is set.

getEnv

getEnv : String -> String

The value of an environment variable, which must be set. Behaves as lookupEnv, but errors instead of returning Nothing when the variable is unset.

getEnvironment

getEnvironment : () -> [(String, String)]

The whole environment, as name-value pairs.

Exiting

exitWith

exitWith : forall (a : 1T) -> Int -> a

Terminates the program, reporting success for an exit code of 0 and failure for any other. Called from a forked thread, terminates that thread alone. Its result type is universally quantified since, like Void, it never actually produces a value.

exitSuccess / exitFailure

exitSuccess : forall (a : 1T) -> () -> a
exitFailure : forall (a : 1T) -> () -> a

Shorthands for exitWith 0 and exitWith 1, respectively.