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
Standard types, classes and related functions
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
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.