diff --git a/src/additional-information.md b/src/additional-information.md index a633b68b..2620569c 100644 --- a/src/additional-information.md +++ b/src/additional-information.md @@ -6,14 +6,14 @@ More information about the Flix programming language can be found in: language researchers. - A series of [blog posts](./blog-posts.md) written by the community. -### Getting Help +## Getting Help If you have a question or comment we are happy to help you out on our Gitter channel: [https://gitter.im/flix/Lobby](https://gitter.im/flix/Lobby) -### Reporting a Bug +## Reporting a Bug If you encounter a bug, you can report it here: diff --git a/src/applicative-for-yield.md b/src/applicative-for-yield.md index bc9a7e8d..1034ee21 100644 --- a/src/applicative-for-yield.md +++ b/src/applicative-for-yield.md @@ -1,11 +1,11 @@ -## Applicative For-Yield +# Applicative For-Yield In addition to the monadic `forM` expression, Flix supports an applicative `forA` expression that builds on the `Applicative` trait. The `forA` construct makes it simple to write error-handling code which uses the `Validation[e, t]` data type. -### Working with Validations +## Working with Validations We can use the `forA` expression to validate user input while collecting all errors. @@ -61,7 +61,7 @@ evaluates to: Success(Connection(luckyluke, password12356789)) ``` -### Applicatives are Independent Computations +## Applicatives are Independent Computations We can write a monadic `forM` expression where the result of one monadic operation is used as the input to another monadic operation. For example: @@ -96,7 +96,7 @@ then the Flix compiler emits a compiler error: because the computations of `x` and `y` are _independent_ and hence the value of `x` is _not_ in scope when we define the value of `y`. -### Desugaring +## Desugaring The `forA` expression is syntactic sugar for uses of `Functor.map` and `Applicative.ap`. diff --git a/src/arrays.md b/src/arrays.md index 1588673e..437192cd 100644 --- a/src/arrays.md +++ b/src/arrays.md @@ -1,4 +1,4 @@ -## Arrays +# Arrays Flix supports mutable _scoped_ arrays. An array is a fixed-length mutable sequence of elements that share the same type. Arrays are laid out consecutively @@ -26,7 +26,7 @@ recommend that arrays are used sparingly. Instead, we recommend using the > **Hint:** Use `MutList` if you need a _growable_ mutable sequence of elements. -### Array Literals +## Array Literals The syntax of an array literal is of the form `Array#{e1, e2, e3, ...} @ r` where `e1`, `e2`, and so forth are _element expressions_, and `r` is the _region @@ -46,7 +46,7 @@ refer to the chapter on [Regions](regions.md). Running the program prints `Array#{"Apple", "Pear", "Mango"}`. -### Allocating Arrays +## Allocating Arrays We can allocate an array of size `n` filled with the same element using the `Array.repeat` function. For example: @@ -84,7 +84,7 @@ region rc { Note that we must pass the region `rc` as an argument to `List.toArray` since the function must know to which region the returned array should belong. -### Allocating Arrays with Uninitialized Elements +## Allocating Arrays with Uninitialized Elements We can use the `Array.empty` function to create an array of a given length where the content of the array is uninitialized. For example: @@ -110,7 +110,7 @@ Flix does not have a `null` value, but one can be indirectly introduced by reading from improperly initialized arrays which can lead to `NullPointerException`s. -### Reading from and Writing to Arrays +## Reading from and Writing to Arrays We can retrieve or update the element at a specific position in an array using `Array.get` and `Array.put`, respectively. For example: @@ -141,7 +141,7 @@ let strings = Array.put("World", 1); ``` -### Slicing Arrays +## Slicing Arrays We can slice arrays using `Array.slice`. A slice of an array is a new (shallow) copy of a sub-range of the original array. For example @@ -156,7 +156,7 @@ region rc { which prints `Array#{"Pear"}` when run. -### Taking the Length of an Array +## Taking the Length of an Array We can compute the length of an array using the `Array.length` function. For example @@ -174,7 +174,7 @@ which prints `3` when run. > we recommend to use functions such as `Array.count`, `Array.forEach`, and > `Array.transform`. -### Additional Array Operations +## Additional Array Operations The `Array` module offers an extensive collection of functions for working with arrays. For example, `Array.append`, `Array.copyOfRange`, `Array.findLeft`, diff --git a/src/associated-effects.md b/src/associated-effects.md index 797692ed..e0ba75c8 100644 --- a/src/associated-effects.md +++ b/src/associated-effects.md @@ -1,4 +1,4 @@ -## Associated Effects +# Associated Effects We have seen how associated types increase the flexibility of traits by allowing each instance to specify concrete types for the associated types. Associated @@ -84,7 +84,7 @@ instance Dividable[Int32] { } ``` -### Associated Effects and Regions +## Associated Effects and Regions We often want to use associated effects in combination with regions. diff --git a/src/associated-types.md b/src/associated-types.md index b7da9a35..727b5279 100644 --- a/src/associated-types.md +++ b/src/associated-types.md @@ -1,4 +1,4 @@ -## Associated Types +# Associated Types An associated type is a type member of a trait that is specified by each trait instance. Associated types are often considered a more natural alternative to @@ -104,7 +104,7 @@ If we had such overlapping instances, an expression like `Addable.add(Set#{}, Set#{})` would become ambiguous: Are we adding two sets? Or are we adding the empty set to a set? -### Example: A `ForEach` Trait +## Example: A `ForEach` Trait We can use associated types to define a trait for collections that have a `forEach` function: @@ -152,7 +152,7 @@ instance ForEach[String] { } ``` -### Example: A `Collection` Trait +## Example: A `Collection` Trait As another example, we can define a trait for collections: @@ -190,7 +190,7 @@ instance Collection[Set[a]] with Order[a] { } ``` -### Equality Constraints +## Equality Constraints We sometimes want to write polymorphic functions where we _restrict_ an associated type. @@ -211,7 +211,7 @@ Specifically, the equality constraint `Collection.Elm[t] ~ Int32` assert that This restriction ensures that the elements of the collection are integers and allows us to call `List.sum`. -### Default Types +## Default Types We can define a default type for an associated type. diff --git a/src/automatic-derivation.md b/src/automatic-derivation.md index f550f1ca..3346236c 100644 --- a/src/automatic-derivation.md +++ b/src/automatic-derivation.md @@ -1,4 +1,4 @@ -## Automatic Derivation +# Automatic Derivation Flix supports automatic derivation of several traits, including: @@ -8,7 +8,7 @@ Flix supports automatic derivation of several traits, including: - `Sendable` — to enable the values of an (immutable) type to be sent over a channel. - `Coerce` - to convert simple data types to their underlying representation. -### Derivation of Eq and Order +## Derivation of Eq and Order We can automatically derive instances of the `Eq` and `Order` traits using the `with` clause in the `enum` declaration. For example: @@ -35,7 +35,7 @@ def main(): Unit \ IO = > **Note**: Automatic derivation of `Eq` and `Order` requires that the inner > types of the `enum` implement `Eq` and `Order` themselves. -### Derivation of ToString +## Derivation of ToString We can also automatically derive `ToString` instances: @@ -63,7 +63,7 @@ which prints: A Circle(123), Square(123), and Rectangle(123, 456) walk into a bar. ``` -### Derivation of Sendable +## Derivation of Sendable We can automatically derive implementations of the `Sendable` trait (which allow values of a specific type to be sent over a channel). For example: @@ -106,7 +106,7 @@ Because it takes a type parameter of kind 'Region'. This is because mutable data is not safe to share between threads. -### Derivation of Coerce +## Derivation of Coerce We can automatically derive implementations of the `Coerce` trait. The `Coerce` trait converts a simple (one-case) data type diff --git a/src/blog-posts.md b/src/blog-posts.md index f459e993..5754bb34 100644 --- a/src/blog-posts.md +++ b/src/blog-posts.md @@ -1,4 +1,4 @@ -## Blog Posts +# Blog Posts A few people are writing about various aspects of Flix on their blogs: diff --git a/src/boxing-and-unboxing.md b/src/boxing-and-unboxing.md index 20781953..f76657af 100644 --- a/src/boxing-and-unboxing.md +++ b/src/boxing-and-unboxing.md @@ -1,11 +1,11 @@ -## Boxing and Unboxing +# Boxing and Unboxing Unlike Java, Flix never performs implicit boxing or unboxing of values. We believe auto boxing is a design flaw and do not plan to support it. Hence, primitive values must be manually boxed and unboxed. -### Boxing +## Boxing The following example shows how to box a primitive integer: @@ -19,7 +19,7 @@ Here the call to `Box.box(x)` returns an `Integer` object. Since `i` is an object, we can call `toString` on it. Boxing is a pure operation, but calling `toString` has the `IO` effect. -### Unboxing +## Unboxing The following example shows how to unbox two Java `Integer` objects: diff --git a/src/bug-and-unreachable.md b/src/bug-and-unreachable.md index 4743f2a5..6d52be45 100644 --- a/src/bug-and-unreachable.md +++ b/src/bug-and-unreachable.md @@ -1,4 +1,4 @@ -## `bug!` and `unreachable!` +# `bug!` and `unreachable!` Flix supports two special "functions": `bug!` and `unreachable!` that can be used to indicate when an diff --git a/src/build.md b/src/build.md index 41dec7ed..ecf95d3b 100644 --- a/src/build.md +++ b/src/build.md @@ -1,9 +1,9 @@ -## Build Management +# Build Management We now discuss the build commands. Each command can be executed from the command line, from the REPL, and from VSCode. -### Creating a New Project +## Creating a New Project We can create a new project, inside a directory, with the `init` command. @@ -30,13 +30,13 @@ The `flix.toml` manifest file is discussed in the next section. > **Tip:** The `init` command is safe to use; it will only create files that do > not already exist. -### Checking a Project +## Checking a Project We can check a project for compiler errors with the `check` command. During development, the `check` command is preferable to the `build` command because it skips code generation (and hence is significantly faster). -### Building a Project +## Building a Project We can compile a project with the `build` command. Running the `build` command will compile the entire project and emit bytecode, i.e. compiled Java classes, @@ -45,7 +45,7 @@ to the `build` directory. Flix has no `clean` command. Deleting the `build` directory serves the same purpose. -### Building a JAR-file +## Building a JAR-file We can compile a project to a JAR-file with the `build-jar` command. The `build-jar` command emits a `artifact/project.jar` file. If there is `main` @@ -61,7 +61,7 @@ on JAR-files. > **Note:** `build-jar` automatically invokes the `build` command. -### Building a fat JAR-file (bundling all dependencies) +## Building a fat JAR-file (bundling all dependencies) We can compile a project to a single standalone fat JAR-file with the `build-fatjar` command. The `build-fatjar` command emits a @@ -74,7 +74,7 @@ directory. > **Note:** `build-fatjar` automatically invokes the `build` command. -### Building a Flix Project +## Building a Flix Project We can bundle a project into a Flix package file (fpkg) with the `build-pkg` command. Running the `build-pkg` command emits a `artifact/project.fpkg` file. @@ -83,12 +83,12 @@ A Flix package file (fpkg) is essentially zip-file of the project source code. A Flix package, together with its `flix.toml` manifest, can be published on GitHub. -### Running a Project +## Running a Project We do not have to build a JAR-file to run a project, we can simply use the `run` command which will compile and run the main entry point. -### Testing a Project +## Testing a Project We can use the `test` command to run all test cases in a project. Flix will collect all functions marked with `@Test`, execute them, and print a summary of diff --git a/src/calling-methods.md b/src/calling-methods.md index 81b2a5e3..50d5689c 100644 --- a/src/calling-methods.md +++ b/src/calling-methods.md @@ -1,4 +1,4 @@ -## Calling Object Methods +# Calling Object Methods In Flix, we can call methods on Java objects using syntax similar to Java. diff --git a/src/chains-and-vectors.md b/src/chains-and-vectors.md index 0939c7ce..f1273aea 100644 --- a/src/chains-and-vectors.md +++ b/src/chains-and-vectors.md @@ -1,4 +1,4 @@ -## Chains and Vectors +# Chains and Vectors In addition to immutable `List`s, Flix also supports immutable `Chain`s and `Vector`s. @@ -23,7 +23,7 @@ When to use `List`, `Chain`, or `Vector`?: - The `Chain` data structure is more rarely used, but shines when fast appends are required. -### Chains +## Chains A `Chain[t]` is an immutable linked sequence of elements. @@ -53,7 +53,7 @@ println(c) which prints `Chain#{1}` when compiled and executed. -### Vectors +## Vectors A `Vector[t]` is an immutable fixed-length sequence of contiguous elements of type `t`. diff --git a/src/checked-casts.md b/src/checked-casts.md index 6d56058a..c0c381e6 100644 --- a/src/checked-casts.md +++ b/src/checked-casts.md @@ -1,4 +1,4 @@ -## Checked Type and Effect Casts +# Checked Type and Effect Casts The Flix type and effect system – by design – does not support sub-typing nor sub-effecting. To work around these limitations, which are rare in practice, @@ -11,7 +11,7 @@ Flix has two _safe_ upcast constructs: > be _safe_. The Flix compiler will check at compile-time that every checked > cast cannot go wrong. -### Checked Type Casts +## Checked Type Casts The following program: @@ -56,7 +56,7 @@ let _: ##java.lang.Object = checked_cast(null); let _: ##java.lang.String = checked_cast(null); ``` -### Checked Effect Casts +## Checked Effect Casts The following program: @@ -102,7 +102,7 @@ The `checked_ecast` construct allows us to pretend that `x + 1` has the `IO` eff > require their function arguments to have a specific effect. Instead they > should be effect polymorphic. -### Function Types +## Function Types Neither the `checked_cast` nor the `checked_ecast` constructs work on function types. diff --git a/src/companion-modules.md b/src/companion-modules.md index 1537cc82..f1976003 100644 --- a/src/companion-modules.md +++ b/src/companion-modules.md @@ -1,9 +1,9 @@ -## Companion Modules +# Companion Modules In Flix every enum and trait declaration is associated with a _companion module_. -### Enum Companions +## Enum Companions When we declare an enum, its type and cases are automatically available inside its companion module. For example, we can write: @@ -27,7 +27,7 @@ mod Color { Here the `Color` type and the `Red`, `Green`, and `Blue` cases are automatically in scope within the companion `Color` module. -### Trait Companions +## Trait Companions Every trait declaration also gives rise to a companion module. diff --git a/src/creating-objects.md b/src/creating-objects.md index 2ab6f44b..fd42f8e8 100644 --- a/src/creating-objects.md +++ b/src/creating-objects.md @@ -1,4 +1,4 @@ -## Creating Objects +# Creating Objects In Flix, we can create objects using syntax similar to Java. diff --git a/src/debugging.md b/src/debugging.md index 5d72bb70..5e39d2bc 100644 --- a/src/debugging.md +++ b/src/debugging.md @@ -1,4 +1,4 @@ -## Debugging +# Debugging When debugging, it is often helpful to output the value of an expression or variable. @@ -30,7 +30,7 @@ print debugging inside pure functions. We could make our `sum` function have the `IO` effect, but that is rarely what we want. Instead, Flix has a built-in debugging facility that allows us to do print-line debugging. -### The `Debug.dprintln` Function +## The `Debug.dprintln` Function Instead, we can use the `Debug.dprintln` function and write: @@ -47,7 +47,7 @@ Inside the `sum` function, the `dprintln` has the effect `Debug`, but due to its special nature, the `Debug` effect "disappears" once we exit the function, i.e. it is not part of its type and effect signature. -### Debugging with Source Locations +## Debugging with Source Locations We can use the special _debug string interpolator_ to add source locations to our print statements: diff --git a/src/declaring-modules.md b/src/declaring-modules.md index 471bb1cc..d8bbd93f 100644 --- a/src/declaring-modules.md +++ b/src/declaring-modules.md @@ -1,4 +1,4 @@ -## Declaring Modules +# Declaring Modules As we have already seen, modules can be declared using the `mod` keyword: @@ -50,7 +50,7 @@ def main(): Unit \ IO = buyGift() ``` -### Accessibility +## Accessibility A module member `m` declared in module `A` is accessible from another module `B` if: diff --git a/src/default-handlers.md b/src/default-handlers.md index 0c6d2a62..5e2ebad5 100644 --- a/src/default-handlers.md +++ b/src/default-handlers.md @@ -1,4 +1,4 @@ -## Default Handlers +# Default Handlers Flix supports **default handlers** which means that an effect can declare a handler that translates the effect into the `IO` effect. This allows `main` (and diff --git a/src/effect-oriented-programming.md b/src/effect-oriented-programming.md index 44856924..b0b486e8 100644 --- a/src/effect-oriented-programming.md +++ b/src/effect-oriented-programming.md @@ -1,4 +1,4 @@ -## Effect-Oriented Programming +# Effect-Oriented Programming Programming with effects requires a new mindset, _an effect-oriented mindset_. @@ -18,7 +18,7 @@ that `IO` effect should be _close_ to the `main` function. We now illustrate these points with an example. -#### A Guessing Game — The Wrong Way +## A Guessing Game — The Wrong Way Consider the following program written in a mixed style of Flix and Java: @@ -78,7 +78,7 @@ Programming in a effect-oriented style means that we should define effects for every action that interacts with the outside world. We should then _handle_ these effects close to the `main` function. -#### A Guessing Game — The Right Way +## A Guessing Game — The Right Way Here is what we should have done: diff --git a/src/effect-polymorphism.md b/src/effect-polymorphism.md index 54fb1bee..cd9336f7 100644 --- a/src/effect-polymorphism.md +++ b/src/effect-polymorphism.md @@ -1,4 +1,4 @@ -## Effect Polymorphism +# Effect Polymorphism In Flix, we can express that a function is pure (i.e. has no side-effects): @@ -59,7 +59,7 @@ def strange(a: Array[t, r]): Unit \ {r, Clock, Net, IO} This function has a heap effect `r` and three primitive effects: `Clock`, `Net`, and `IO`. -### Higher-Order Functions +## Higher-Order Functions When we write higher-order functions, we must think carefully about their effect behavior. @@ -125,7 +125,7 @@ It's important to understand that there can be several ways to write the same effect set. For example, `ef1 + ef2` is equivalent to `ef2 + ef1`, as one would expect. -### Effect Exclusion +## Effect Exclusion A novel feature of Flix is its support for [effect exclusion](https://dl.acm.org/doi/abs/10.1145/3607846). In simple terms, effect @@ -152,7 +152,7 @@ Here the `recoverWith` function takes two function arguments: the function `f` that may throw an exception and a handler `h` which can handle the error. Notably, the effect system enforces that `h` cannot itself throw an exception. -### Sub-Effecting +## Sub-Effecting > **Note:** This feature is not yet enabled. diff --git a/src/effect-system.md b/src/effect-system.md index e36213cd..e8253422 100644 --- a/src/effect-system.md +++ b/src/effect-system.md @@ -60,7 +60,7 @@ Before we continue, it is important to understand that Flix has three types of e We describe how traits and effects interact in the section on [Associated Effects](./associated-effects.md). -### Direct Style +## Direct Style Flix is a so-called _direct-style_ programming language with a traditional type and effect system. This is in contrast to so-called _functional effect systems_ diff --git a/src/effects-and-handlers.md b/src/effects-and-handlers.md index d5ca0940..fd7361de 100644 --- a/src/effects-and-handlers.md +++ b/src/effects-and-handlers.md @@ -1,4 +1,4 @@ -## Effects and Handlers +# Effects and Handlers Flix supports algebraic effects and handlers in the style of [Eff](https://www.eff-lang.org/) and [Koka](https://koka-lang.github.io/). @@ -13,7 +13,7 @@ reader take a look at: We begin a type of effect most programmers are familiar with: *exceptions*. -### Non-Resumable Effects: Exceptions +## Non-Resumable Effects: Exceptions We can use effects and handlers to implement exceptions. For example: @@ -82,7 +82,7 @@ Because the first two calls to `divide` succeed, whereas the last call will raise a `DivByZero` exception. Notably, the Flix type and effect system can track the exception effect through the effect polymorphic call to `List.map`. -### Resumable Effects +## Resumable Effects Flix also supports resumable effects. For example: @@ -123,7 +123,7 @@ captures the current continuation and finds the closest handler (in `main`), which **resumes** the computation from within `greeting` using the current hour of the day, as obtained from system clock. -### Multiple Effects and Handlers +## Multiple Effects and Handlers We can write functions that use multiple effects: @@ -157,7 +157,7 @@ string to the environment. We use both effects in `greeting`. In `main`, we call the continuation with the string `"Bond, James Bond"`. We handle the `Say` effect by printing to the console and resuming the continuation. -### Multiple Resumptions +## Multiple Resumptions Flix supports algebraic effects with multiple resumptions. We can use such effects to implement async/await, backtracking search, cooperative @@ -227,7 +227,7 @@ handlers matters*! If we handle the `Exc` effect first then we obtain the list `Some(heads) :: Some(tails) :: None :: Nil`. If, on the other hand, we handle `Exc` last then the whole computation fails with `None`. -### Algebraic Effects and Monads +## Algebraic Effects and Monads Flix supports algebraic effect handlers and [monads](./monadic-for-yield.md) because we want to support both styles of programming: @@ -243,7 +243,7 @@ to model interaction with the outside world but prefer the `Option` and `Result` data types for simple error handling. Working with `Option`s and `Result`s is more pleasant with [monadic syntax](./monadic-for-yield.md). -### Limitation: Polymorphic Effects +## Limitation: Polymorphic Effects The Flix type and effect system does not yet support polymorphic effects.[^1] @@ -282,7 +282,7 @@ eff ThrowInt32 { } ``` -### Unhandled Effects in New Object and Spawn Expressions +## Unhandled Effects in New Object and Spawn Expressions Flix does not permit unhandled effects in new object expressions nor in spawn expressions. diff --git a/src/enums.md b/src/enums.md index 366e09ea..27ff0bf8 100644 --- a/src/enums.md +++ b/src/enums.md @@ -1,6 +1,6 @@ -## Enums +# Enums -### Enumerated Types +## Enumerated Types Enumerated types are used to define a type that has a finite (enumerated) set of values. @@ -64,7 +64,7 @@ adding a default case as the last case. A default case is written with an underscore `case _ => ???`. -### Recursive Types +## Recursive Types Recursive types are used to define types that are self-referential. @@ -98,7 +98,7 @@ If the tree is a leaf its value is simply returned. Otherwise the function recurses on both subtrees and adds their results. -### Polymorphic Types +## Polymorphic Types Polymorphic types are types parameterized by other types. @@ -142,7 +142,7 @@ enum Result[e, t] { } ``` -### Shorthand Enum Syntax +## Shorthand Enum Syntax A typical enum may look like: @@ -168,7 +168,7 @@ enum Weekday { This shorthand syntax is always available, but should only be used for simple enums. -### Singleton Enum Syntax +## Singleton Enum Syntax An enum with a single case: diff --git a/src/essential-traits.md b/src/essential-traits.md index e27ee9a1..b99a7430 100644 --- a/src/essential-traits.md +++ b/src/essential-traits.md @@ -1,9 +1,9 @@ -## Essential Traits +# Essential Traits Practical programming in Flix requires knowledge of at least three traits: `Eq`, `Order`, and `ToString`. -### The Eq Trait +## The Eq Trait The `Eq` trait captures when two values of a specific type are equal: @@ -22,7 +22,7 @@ trait Eq[a] { To implement `Eq`, we only have to implement the `eq` function. When we implement `eq` we automatically get an implementation of `Eq.neq`. -### The Order Trait +## The Order Trait The `Order` trait captures when one value is smaller or equal to another value of the same type: @@ -56,7 +56,7 @@ When we implement `compare`, we automatically get implementations of `Order.less`, `Order.lessThan`, `Order.greater`, `Order.greaterEqual`, `Order.max`, and `Order.min`. -### The ToString Trait +## The ToString Trait The `ToString` trait is used to obtain a string representation of a specific value: diff --git a/src/exceptions.md b/src/exceptions.md index a54312d7..b960b556 100644 --- a/src/exceptions.md +++ b/src/exceptions.md @@ -1,4 +1,4 @@ -## Exceptions +# Exceptions In Flix, we can catch Java exceptions using the `try-catch` construct. The construct is similar to the one in Java, but the syntax is slightly different. diff --git a/src/extending-classes-and-interfaces.md b/src/extending-classes-and-interfaces.md index 68e17706..7c91fc9c 100644 --- a/src/extending-classes-and-interfaces.md +++ b/src/extending-classes-and-interfaces.md @@ -1,4 +1,4 @@ -## Classes and Interfaces +# Classes and Interfaces Flix allows us to create objects that extend a Java class or implements a Java interface. diff --git a/src/foreach.md b/src/foreach.md index 4ffa84a0..a87781df 100644 --- a/src/foreach.md +++ b/src/foreach.md @@ -1,4 +1,4 @@ -## Foreach +# Foreach Flix supports a traditional _foreach_ construct that enables imperative iteration through collections. @@ -53,7 +53,7 @@ def isExcotic(fruit: String): Bool = match fruit { } ``` -### Adding Optional Braces for Visual Clarity +## Adding Optional Braces for Visual Clarity We can sometimes improve the visual clarity of a `foreach` expression by adding braces: @@ -72,7 +72,7 @@ def main(): Unit \ IO = The braces have no impact on the meaning of the `foreach` loop; they are purely stylistic. -### The ForEach Trait +## The ForEach Trait We can use the `foreach` syntax to iterate through any collection type that implements the `ForEach` trait. In particular, the `ForEach` trait diff --git a/src/frequently-asked-questions.md b/src/frequently-asked-questions.md index 11ac3d74..dbba0642 100644 --- a/src/frequently-asked-questions.md +++ b/src/frequently-asked-questions.md @@ -1,6 +1,6 @@ -## Frequently Asked Questions +# Frequently Asked Questions -### Does Flix supports constants? +## Does Flix supports constants? Yes and no. Flix does not support top-level constants. You can, however, declare a pure function which takes zero arguments: diff --git a/src/functional-predicates.md b/src/functional-predicates.md index bcfc49a2..39fea17e 100644 --- a/src/functional-predicates.md +++ b/src/functional-predicates.md @@ -1,4 +1,4 @@ -## Functional Predicates +# Functional Predicates We sometimes run into a situation where we would like to use a logic predicate, but not to exhaustively enumerate all of its tuples. diff --git a/src/getting-started.md b/src/getting-started.md index 5e2472a9..7744d333 100644 --- a/src/getting-started.md +++ b/src/getting-started.md @@ -24,7 +24,7 @@ Once you have Java 21+ installed there are two ways to proceed: - You can use the [Flix VSCode extension](https://marketplace.visualstudio.com/items?itemName=flix.flix) (__highly recommended__) or - You can run the Flix compiler from the command line. -### Using Flix from Visual Studio Code (VSCode) +## Using Flix from Visual Studio Code (VSCode) Flix comes with a fully-featured VSCode plugin. Follow these steps to get started: @@ -41,7 +41,7 @@ A screenshot of the Flix Visual Studio Code extension in action: ![Visual Studio Code1](images/vscode1.png) -### Using Flix from Neovim +## Using Flix from Neovim Flix can also be used from [Neovim](https://neovim.io/). Follow these steps to get started: @@ -52,7 +52,7 @@ get started: nvim --version ``` -#### Neovim Flix plugin +### Neovim Flix plugin There is a Lua [plugin](https://github.com/flix/nvim) which provides an LSP configuration for the native neovim lsp, and several functions to interact with the flix cli. It's repo has detailed installation and configuration instructions. It can be installed with a plugin manager of choice or cloned locally into your neovim runtime path. @@ -117,7 +117,7 @@ The snippet above provides the following keybindings. ![Visual Studio Code1](images/neovim.png) -#### Manual Neovim Configuration +### Manual Neovim Configuration If you would rather setup the LSP server yourself the code from the plugin is as follows. @@ -183,11 +183,11 @@ vim.api.nvim_create_autocmd("FileType", { > place this code in your `$HOME/.config/nvim/init.lua` or wherever you configure your lsp in neovim. -### Using Flix from Emacs +## Using Flix from Emacs Flix can be used from [Emacs](https://www.gnu.org/software/emacs/) as well by installing the [flix-mode](https://codeberg.org/mdiin/flix-mode) package. Follow the instructions there to get started writing Flix code in Emacs. -### Using Flix from the Command Line +## Using Flix from the Command Line Flix can also be used from the command line. Follow these steps: @@ -197,7 +197,7 @@ Flix can also be used from the command line. Follow these steps: > 4. Run `java -jar flix.jar run` to compile and run the project. -### Using nix +## Using nix Flix can also be installed using the [nix package manager](https://nixos.org/). To install for the currently running shell run: @@ -214,7 +214,7 @@ $ nix-env -i flix Then run `flix run` in your project directory. -### Troubleshooting +## Troubleshooting The most common reasons for Flix not working are (a) the `java` command not being on your `PATH`, (b) the `JAVA_HOME` environmental variable not being set diff --git a/src/hello-world.md b/src/hello-world.md index 0ccb8830..7b6895b8 100644 --- a/src/hello-world.md +++ b/src/hello-world.md @@ -1,4 +1,4 @@ -## Hello World +# Hello World We can now see the famous _Hello World_ program in `src/Main.flix` file: diff --git a/src/higher-kinded-types.md b/src/higher-kinded-types.md index d1f40173..68d1a9a0 100644 --- a/src/higher-kinded-types.md +++ b/src/higher-kinded-types.md @@ -1,4 +1,4 @@ -## Higher-Kinded Types +# Higher-Kinded Types Flix supports [higher-kinded types](https://en.wikipedia.org/wiki/Kind_(type_theory)), hence traits can @@ -37,7 +37,7 @@ instance ForEach[List] { } ``` -### The Flix Kinds +## The Flix Kinds Flix supports the following kinds: @@ -74,7 +74,7 @@ Flix requires explicit kind annotations in four situations: The most common scenario where you will need a kind annotation is when you want a type parameter or type member to range over an effect. -### Higher-Kinded Types vs. Associated Types +## Higher-Kinded Types vs. Associated Types In practice higher-kinded types and associated types can be used to define similar abstractions. diff --git a/src/holes.md b/src/holes.md index 25fcc0e2..09d3b99a 100644 --- a/src/holes.md +++ b/src/holes.md @@ -1,4 +1,4 @@ -## Anonymous and Named Holes +# Anonymous and Named Holes During development, Flix encourages the use of holes for incomplete code. For example: @@ -31,7 +31,7 @@ def length(l: List[a]): Int32 = match l { Flix requires that each named hole has a unique name. -### Variable Holes and Auto-Completion +## Variable Holes and Auto-Completion Flix has support for a special _variable hole_ which enables type-driven auto-completion suggestions. For example, in the program: diff --git a/src/identifiers.md b/src/identifiers.md index b4150134..389ed29e 100644 --- a/src/identifiers.md +++ b/src/identifiers.md @@ -1,4 +1,4 @@ -## Identifiers +# Identifiers Flix has several types of identifiers: diff --git a/src/if-then-else.md b/src/if-then-else.md index 1b7a3d2f..a3586210 100644 --- a/src/if-then-else.md +++ b/src/if-then-else.md @@ -1,4 +1,4 @@ -## If-then-else +# If-then-else Flix supports the usual *if-then-else* expression: @@ -10,7 +10,7 @@ which evaluates to `Hello`. But `if` guards are also supported in other parts of the language. -### Guarded Pattern Matches +## Guarded Pattern Matches We can use an `if`-guard in a pattern match: @@ -21,7 +21,7 @@ def isSquare(s: Shape): Bool = match s { } ``` -### Guarded Datalog Rules +## Guarded Datalog Rules We can use an `if`-guard in a Datalog rule: diff --git a/src/java-collections.md b/src/java-collections.md index 12eb5460..320b2322 100644 --- a/src/java-collections.md +++ b/src/java-collections.md @@ -1,4 +1,4 @@ -## Java Collections +# Java Collections Flix has support for conversion from and to Java collections. @@ -17,7 +17,7 @@ import java.util.{TreeMap => JTreeMap} The following functions are available in the [Adaptor](https://api.flix.dev/Adaptor.html) module: -### Flix to Java +## Flix to Java The following functions _convert_ Flix collections to Java collections: @@ -46,7 +46,7 @@ Each function constructs a new collection and copies all its elements into it. Hence each operation takes at least linear time. The result is a normal Java collection (which can be modified). -### Java to Flix +## Java to Flix The following functions _convert_ Java collections to Flix collections: diff --git a/src/lattice-semantics.md b/src/lattice-semantics.md index e78f9118..38ac2da3 100644 --- a/src/lattice-semantics.md +++ b/src/lattice-semantics.md @@ -1,4 +1,4 @@ -## Using Flix to Solve Constraints on Lattices +# Using Flix to Solve Constraints on Lattices Flix supports not only _constraints on relations_, but also _constraints on lattices_. @@ -154,7 +154,7 @@ pub def main(): Unit \ IO = Note the careful use of `;` to designate lattice semantics. -### Using Lattice Semantics to Compute Shortest Paths +## Using Lattice Semantics to Compute Shortest Paths We can also use lattice semantics to compute shortest paths. diff --git a/src/library-effects.md b/src/library-effects.md index efa299f6..fd198393 100644 --- a/src/library-effects.md +++ b/src/library-effects.md @@ -1,9 +1,9 @@ -## Library Effects +# Library Effects The Flix Standard Library comes with a collection of algebraic effects and handlers. -### Clock +## Clock Flix defines a `Clock` effect to access the time since the [UNIX epoch](https://en.wikipedia.org/wiki/Unix_time): @@ -27,7 +27,7 @@ mod Clock { Every effect in the standard library comes with `handle` and `runWithIO` functions. -#### Example: Using `Clock` +### Example: Using `Clock` ```flix def main(): Unit \ IO = @@ -37,7 +37,7 @@ def main(): Unit \ IO = } with Clock.runWithIO ``` -### Console +## Console Flix defines a `Console` effect to read from and write to shell: @@ -60,7 +60,7 @@ eff Console { } ``` -#### Example: Using `Console` +### Example: Using `Console` ```flix def main(): Unit \ IO = @@ -71,7 +71,7 @@ def main(): Unit \ IO = } with Console.runWithIO ``` -### FileReadWithResult +## FileReadWithResult Flix defines a `FileReadWithResult` effect to read from the file system: @@ -124,7 +124,7 @@ eff FileReadWithResult { } ``` -#### Example: Using `FileReadWithResult` +### Example: Using `FileReadWithResult` ```flix def main(): Unit \ IO = @@ -138,7 +138,7 @@ def main(): Unit \ IO = } with FileReadWithResult.runWithIO ``` -### FileWriteWithResult +## FileWriteWithResult Flix defines a `FileWriteWithResult` effect to write to the file system: @@ -176,7 +176,7 @@ eff FileWriteWithResult { } ``` -#### Example: Using `FileWriteWithResult` +### Example: Using `FileWriteWithResult` ```flix def main(): Unit \ IO = @@ -190,7 +190,7 @@ def main(): Unit \ IO = } with FileWriteWithResult.runWithIO ``` -### HttpWithResult +## HttpWithResult Flix defines a `HttpWithResult` effect to communicate over HTTP: @@ -227,7 +227,7 @@ mod HttpWithResult { } ``` -#### Example: Using `HttpWithResult` +### Example: Using `HttpWithResult` ```flix def main(): Unit \ {Net, IO} = @@ -241,7 +241,7 @@ def main(): Unit \ {Net, IO} = } with HttpWithResult.runWithIO ``` -### Logger +## Logger Flix defines a `Logger` effect for logging messages: @@ -273,7 +273,7 @@ mod Logger { } ``` -#### Example: Using `Logger` +### Example: Using `Logger` ```flix def main(): Unit \ IO = @@ -283,7 +283,7 @@ def main(): Unit \ IO = } with Logger.runWithIO ``` -### ProcessWithResult +## ProcessWithResult Flix defines a `ProcessWithResult` effect for running commands outside of the JVM: @@ -316,7 +316,7 @@ def execWithEnv(cmd: String, args: List[String], env: Map[String, String]) : Result[IoError, ProcessHandle] \ ProcessWithResult ``` -#### Example: Using `ProcessWithResult` +### Example: Using `ProcessWithResult` ```flix def main(): Unit \ {Exec, IO} = @@ -328,7 +328,7 @@ def main(): Unit \ {Exec, IO} = } with ProcessWithResult.runWithIO ``` -### Random +## Random Flix defines a `Random` effect for the generation of random values: @@ -354,7 +354,7 @@ eff Random { } ``` -#### Example: Using `Random` +### Example: Using `Random` ```flix def main(): Unit \ {NonDet, IO} = @@ -367,7 +367,7 @@ def main(): Unit \ {NonDet, IO} = } with Random.runWithIO ``` -### Running Multiple Effects +## Running Multiple Effects We can easily combine multiple effects and run them: diff --git a/src/lists.md b/src/lists.md index bcd8257f..1d61b694 100644 --- a/src/lists.md +++ b/src/lists.md @@ -1,4 +1,4 @@ -## Lists +# Lists A list is either the empty list, written as `Nil`, or a cons cell, written as `x :: xs` where `x` is diff --git a/src/local-predicates.md b/src/local-predicates.md index 6304c854..12048103 100644 --- a/src/local-predicates.md +++ b/src/local-predicates.md @@ -1,4 +1,4 @@ -## Local Predicates +# Local Predicates Flix supports an abstract mechanism called _local predicates_. A local predicate, like a local variable, is not visible to the outside. diff --git a/src/main.md b/src/main.md index 3b06ee2a..990a9464 100644 --- a/src/main.md +++ b/src/main.md @@ -1,4 +1,4 @@ -## The Main Function +# The Main Function The entry point of any Flix program is the `main` function which _must_ have the signature: diff --git a/src/monadic-for-yield.md b/src/monadic-for-yield.md index 5dbc77cc..3fd22246 100644 --- a/src/monadic-for-yield.md +++ b/src/monadic-for-yield.md @@ -1,4 +1,4 @@ -## Monadic For-Yield +# Monadic For-Yield Flix supports a monadic _forM-yield_ construct similar to Scala's for-comprehensions and Haskell's do notation. The _forM_ construct is syntactic @@ -21,7 +21,7 @@ evaluates to the list: (1, 1) :: (1, 2) :: (2, 1) :: (2, 2) :: Nil ``` -### Using Guard Expressions +## Using Guard Expressions We can use _guard expressions_ in `forM` expressions. For example, the program: @@ -38,7 +38,7 @@ evaluates to the list: (1, 2) :: Nil ``` -### Working with Options and Results +## Working with Options and Results We can also use `forM` to work with the `Option` data type. For example: @@ -82,7 +82,7 @@ either an error or the input string. Thus the local variables `fstName`, is successful then we print a greeting and return `Ok(())` (i.e., `Ok` of `Unit`). Otherwise, we return an `Err(msg)` value. -### Working with Other Monads +## Working with Other Monads We can use `forM` with other types of `Monad`s, including `Chain` and `Nel`s (non-empty lists). For example, we can write: @@ -104,7 +104,7 @@ Nel((1, 1), (1, 2) :: (2, 1) :: (2, 2) :: Nil) > `if`-guard requires an instance of the `MonadZero` trait which is not > implemented by non-empty list (since such a list cannot be empty). -### Desugaring +## Desugaring The `forM` expression is syntactic sugar for uses of `Monad.flatMap`, `Applicative.point`, and `MonadZero.empty`. diff --git a/src/mutable-collections.md b/src/mutable-collections.md index 9a51b423..73406587 100644 --- a/src/mutable-collections.md +++ b/src/mutable-collections.md @@ -1,4 +1,4 @@ -## Mutable Collections +# Mutable Collections The Flix standard library supports many immutable collections, including options, lists, chains, sets, and maps. We strongly encourage their use. diff --git a/src/nested-and-inner-classes.md b/src/nested-and-inner-classes.md index 0d0c6b97..b3bdc13a 100644 --- a/src/nested-and-inner-classes.md +++ b/src/nested-and-inner-classes.md @@ -1,4 +1,4 @@ -## Nested and Inner Classes +# Nested and Inner Classes Java supports nested static and non-static inner classes: diff --git a/src/next-steps.md b/src/next-steps.md index 8d78c5f1..1a012bbb 100644 --- a/src/next-steps.md +++ b/src/next-steps.md @@ -1,4 +1,4 @@ -## Next Steps +# Next Steps We are now ready write our first real program! diff --git a/src/outdated.md b/src/outdated.md index 9c1483db..15f898a1 100644 --- a/src/outdated.md +++ b/src/outdated.md @@ -1,4 +1,4 @@ -## Finding Outdated Packages +# Finding Outdated Packages We can use the `outdated` command to check if any Flix packages have updates available. diff --git a/src/packages.md b/src/packages.md index aa5e8936..bda7cdb3 100644 --- a/src/packages.md +++ b/src/packages.md @@ -1,4 +1,4 @@ -## Package Management +# Package Management Every non-trivial Flix project should have a `flix.toml` manifest. The manifest contains information about the project and its dependencies. @@ -17,7 +17,7 @@ authors = ["John Doe "] > **Note:** The `flix` field is not yet used, but it will be used in the future. -### Adding Flix Dependencies +## Adding Flix Dependencies We can add dependencies on other Flix packages to the manifest: @@ -29,7 +29,7 @@ We can add dependencies on other Flix packages to the manifest: > **Note:** Flix requires version numbers to follow SemVer. -### Adding Maven Dependencies +## Adding Maven Dependencies We can also add dependencies on Maven packages to the manifest: @@ -38,7 +38,7 @@ We can also add dependencies on Maven packages to the manifest: "org.junit.jupiter:junit-jupiter-api" = "5.9.2" ``` -### Understanding Dependency Resolution +## Understanding Dependency Resolution Flix dependency resolution works as follows: @@ -88,7 +88,7 @@ This happens because `flix/museum` has the following dependency tree: - `flix/museum-restaurant` which depends on - `org.apache.commons:commons-lang3` -### Security +## Security To reduce the risk of supply-chain attacks, every dependency has a **security context** — even if you don't set one explicitly. Security contexts control which language features a dependency may use. Broader security contexts enable diff --git a/src/pattern-matching.md b/src/pattern-matching.md index 479ed42e..7efd1c41 100644 --- a/src/pattern-matching.md +++ b/src/pattern-matching.md @@ -1,6 +1,6 @@ -## Pattern Matching +# Pattern Matching -### Matching on Enums +## Matching on Enums Flix supports pattern matching on algebraic data types. @@ -25,7 +25,7 @@ def area(s: Shape): Int32 = match s { } ``` -### Matching on Records +## Matching on Records The above also works for record types; however, the syntax is slightly different. Let us rewrite the `Shape` type from before, this time using records. @@ -114,7 +114,7 @@ To summarize, here are a few examples of record patterns: - `{ radius | _ }` - a record containg at least the label `radius` - `{ radius | r }` - a record containg at least the label `radius` where the rest of the record is bound to `r` -### Let Pattern Match +## Let Pattern Match In addition to the pattern `match` construct, a let-binding can be used to destruct a value. For example: @@ -153,7 +153,7 @@ let { height | _ } = r; height + height ``` -### Match Lambdas +## Match Lambdas Pattern matches can also be used with lambda expressions. For example: diff --git a/src/precedence.md b/src/precedence.md index 8c134b10..6359131d 100644 --- a/src/precedence.md +++ b/src/precedence.md @@ -1,4 +1,4 @@ -## Precedence +# Precedence 1. Unary operators (`+`, `-`, `~~~`, and `not`) 1. User-defined operators (including operators defined in the standard library such as `|>`) diff --git a/src/primitive-effects.md b/src/primitive-effects.md index 765e4d96..ac252d8b 100644 --- a/src/primitive-effects.md +++ b/src/primitive-effects.md @@ -1,4 +1,4 @@ -## Primitive Effects +# Primitive Effects > **Note:** This page is slightly updated and pending a rewrite. @@ -9,7 +9,7 @@ cannot be undone or reinterpreted. The most important primitive effect is the `IO` effect. -### The `IO` Effect +## The `IO` Effect The `IO` effect represents any action that interacts with the world outside the program. Such actions include printing to the console, creating, reading, and @@ -25,7 +25,7 @@ The `IO` effect, and all other primitive effects, are _viral_. If a function has a primitive effect, all its callers will also have that primitive effect. That is to say, once you have tainted yourself with impurity, you remain tainted. -### The Other Primitive Effects +## The Other Primitive Effects - **NonDet**: The `NonDet` effect represents an almost pure computation. For example, a function that flips a coin is virtually pure; it has no diff --git a/src/primitive-types.md b/src/primitive-types.md index 7d7b8a8d..f8ea4b30 100644 --- a/src/primitive-types.md +++ b/src/primitive-types.md @@ -1,4 +1,4 @@ -## Primitive Types +# Primitive Types Flix supports the primitive types: @@ -21,11 +21,11 @@ Flix supports the primitive types: written without suffix, i.e. `123.0f64` can simply be written as `123.0` and `123i32` can be written as `123`. -### Built-in Literals +## Built-in Literals Flix has built-in syntactic sugar for lists, sets, maps and regex. -#### List Literals +### List Literals A list literal is written using the infix `::` constructor. For example: @@ -45,7 +45,7 @@ Alternatively, the same list can also be written as: List#{1, 2, 3} ``` -#### Set Literals +### Set Literals A set literal is written using the notation `Set#{v1, v2, ...}`. For example: @@ -61,7 +61,7 @@ Set.insert(3, Set.insert(2, Set.insert(1, Set.empty()))) Note that the elements are inserted from left to right, thus 1 is inserted first. -#### Map Literals +### Map Literals A map literal is written using the notation `Map#{k1 => v1, k2 => v2, ...}`. @@ -79,7 +79,7 @@ Map.insert(2, "World", Map.insert(1, "Hello", Map.empty())) Note that similar to sets above, the entries are inserted left to right. In particular, if multiple entries share the same key, the rightmost one overwrites the previous values. -#### Regex Literals +### Regex Literals A regex literal is written using the notation `regex"..."`. For example: diff --git a/src/printing-to-stdout.md b/src/printing-to-stdout.md index 3e1f76be..20e82fbe 100644 --- a/src/printing-to-stdout.md +++ b/src/printing-to-stdout.md @@ -1,4 +1,4 @@ -## Printing to Standard Out +# Printing to Standard Out The Flix Prelude defines the `println` function which prints to standard out. For example: @@ -21,7 +21,7 @@ The `println` function is rightfully effectful, hence it cannot be called from a pure function. To debug a pure function, use the builtin [debugging facilities](./debugging.md). -### The Console Module +## The Console Module The `Console` module defines additional functions for reading from or writing to the terminal: diff --git a/src/publish.md b/src/publish.md index 3d162e19..49496df9 100644 --- a/src/publish.md +++ b/src/publish.md @@ -1,8 +1,8 @@ -## Publishing a Package on GitHub +# Publishing a Package on GitHub Flix packages are published on GitHub. -### Automatically Publishing a Package +## Automatically Publishing a Package Flix can automatically package and publish artifacts on GitHub by following these steps: @@ -46,7 +46,7 @@ Publishing new release... > **Warning:** Be sure to keep your token safe! -### Manually Publishing a Package +## Manually Publishing a Package A package can also be manually published by following these steps: diff --git a/src/purity-reflection.md b/src/purity-reflection.md index a5ff3b07..54dbcb01 100644 --- a/src/purity-reflection.md +++ b/src/purity-reflection.md @@ -1,4 +1,4 @@ -## Purity Reflection +# Purity Reflection > **Note:** This is an advanced feature and should only be used by experts. diff --git a/src/reading-and-writing-fields.md b/src/reading-and-writing-fields.md index 001aa908..fa9091db 100644 --- a/src/reading-and-writing-fields.md +++ b/src/reading-and-writing-fields.md @@ -1,9 +1,9 @@ -## Reading and Writing Fields +# Reading and Writing Fields Flix supports reading object fields and static (class) fields with standard Java syntax. -### Reading Object Fields +## Reading Object Fields We can read an object field as follows: @@ -13,7 +13,7 @@ import java.awt.Point def area(p: Point): Int32 \ IO = p.x * p.y ``` -### Reading Static Fields +## Reading Static Fields We can read a static field as follows: diff --git a/src/records.md b/src/records.md index a802f3c7..dfbd36fa 100644 --- a/src/records.md +++ b/src/records.md @@ -1,10 +1,10 @@ -## Records +# Records Flix supports row polymorphic extensible records. Flix records are immutable (but may contain mutable reference cells). -### Record Literals +## Record Literals A record literal is written with curly braces: @@ -26,7 +26,7 @@ which has type `{ y = Int32, x = Int32 }`. This type is equivalent to `{ x = Int32, y = Int32 }`. In other words, the order of labels within a record type does not matter. -### Label Access +## Label Access We can access the label of a record using a hash: @@ -40,7 +40,7 @@ The type system ensures that we cannot access a label that does not exist. Records are immutable. Once constructed, the values of the record labels cannot be changed. -### Label Update +## Label Update While records are immutable, we can construct a new record with an updated label value: @@ -56,7 +56,7 @@ The expression `{ x = 3 | p1 }` updates the record `p1` with a new value of its record. A record cannot be *updated* with a new label, but it can be *extended* with a new label, as we shall see later. -### Record Extension +## Record Extension We can add a new label to an existing record as follows: @@ -70,7 +70,7 @@ Here the expression `{ +z = 3 | p1 }` extends the record `p1` with a new label `z` such that the result has three labels: `x`, `y`, and `z` all of which are of `Int32` type. -### Record Restriction +## Record Restriction Similarly to record extension, we can also remove a label from a record: @@ -82,7 +82,7 @@ let p2 = { -y | p1 }; Here the record `p2` has the same labels as `p1` except that the `y` label has been removed. -### Row Polymorphism: Open and Closed Records +## Row Polymorphism: Open and Closed Records A function may specify that it requires a record with two labels: @@ -104,7 +104,7 @@ def g(r: {x = Int32, y = Int32 | s}): Int32 = r#x + r#y We can call this function with *any* record as long as it has `x` and `y` labels which are of type `Int32`. We say that the record type of `r` is *open*. -### Named Parameters with Records +## Named Parameters with Records When a function has multiple parameters that share the same type, it is easy to get confused about the right argument order. For example, what does diff --git a/src/redundancy.md b/src/redundancy.md index b36bfe6d..b70566a5 100644 --- a/src/redundancy.md +++ b/src/redundancy.md @@ -1,4 +1,4 @@ -## Redundancy +# Redundancy The Flix compiler aggressively rejects programs that contain unused elements. The idea is to help programmers avoid subtle bugs[^1]. While this can take some @@ -11,7 +11,7 @@ Specifically, the Flix compiler will ensure that a program does not have: - [Useless expressions](#useless-expressions): pure expressions whose values are discarded. - [Must use values](#must-use-values): expressions whose values are unused but their type is marked as `@MustUse`. -### Unused Local Variables +## Unused Local Variables Flix rejects programs with unused variables. @@ -46,7 +46,7 @@ def main(): Unit \ IO = println("The sum is ${x + x}") ``` -### Shadowed Local Variables +## Shadowed Local Variables Flix rejects programs with shadowed variables. @@ -79,7 +79,7 @@ The shadowed variable was declared here: -### Useless Expressions +## Useless Expressions Flix rejects programs with _pure_ expressions whose results are discarded. @@ -108,7 +108,7 @@ The expression has type 'Int32' An expression that has no side-effect and whose result is unused is suspicious, since it could just be removed from the program without changing its meaning. -### Must Use Values +## Must Use Values Flix rejects programs with expressions whose values are discarded but where their type is marked with the `@MustUse` annotation. Function types, and the diff --git a/src/references.md b/src/references.md index a1962afd..06b6508f 100644 --- a/src/references.md +++ b/src/references.md @@ -1,4 +1,4 @@ -## References +# References Flix supports mutable _scoped_ references. A reference is a box whose value can change over time. The three key reference operations are: @@ -19,7 +19,7 @@ returns the content of a reference cell, and the assignment `Ref.put` operation changes the value of a reference cell. Informally, a reference cell can be thought of as an "object" with a single field that can be changed. -### Allocating References +## Allocating References A reference cell is allocated with the `Ref.fresh(rc, e)` function. For example: @@ -33,7 +33,7 @@ region rc { Here we introduce a region named `rc`. Inside the region, we create a reference cell called `c` with the value `42` which we then dereference and print. -### Dereferencing References +## Dereferencing References A reference cell is accessed (dereferenced) with the `Ref.get` function. For example: @@ -48,7 +48,7 @@ region rc { Here the program prints `42 + 42 = 84`. -### Assignment +## Assignment We can update the value of a reference cell. For example: @@ -65,7 +65,7 @@ region rc { Here the program creates a reference cell `c` with the value `0`. We dereference the cell and increment its value three times. Hence the program prints `3`. -### Example: A Simple Counter +## Example: A Simple Counter We can use references to implement a simple counter: @@ -100,7 +100,7 @@ are also scoped. Note that the `newCounter` function requires a region handle to create a new `Counter`. Moreover, note that the functions `getCount` and `increment` both have the `r` effect. -### Aliasing and References to References +## Aliasing and References to References References naturally support aliasing since that is their purpose. For example: @@ -129,7 +129,7 @@ region rc { Here the type of `l2` is `Ref[Ref[Int32, rc], rc]`. -### Mutable Tuples and Records +## Mutable Tuples and Records Flix tuples and records are _immutable_. However, tuples and records may contain mutable references. diff --git a/src/regions.md b/src/regions.md index 712a8fb2..e3e92efc 100644 --- a/src/regions.md +++ b/src/regions.md @@ -1,4 +1,4 @@ -## Regions +# Regions Flix supports _scoped_ mutable memory. In Flix, all mutable memory belongs to a _region_ that is tied to its lexical scope. When execution leaves the lexical @@ -62,7 +62,7 @@ def flatMap(f: a -> List[b] \ ef, l: List[a]): List[b] \ ef = } ``` -### Regions are Values +## Regions are Values A region (or region handle) is a _value_ that can be passed as a function argument. This is useful, for example, when we want to write a reusable function @@ -81,7 +81,7 @@ The function takes a region handle `rc`, allocates a new mutable deque (`MutDeq`) in the given region, inserts all elements of the list `l` in the deque, and returns it. -### Regions are Scoped +## Regions are Scoped Regions and all memory associated with them cannot outlive their lexical scope. diff --git a/src/research-literature.md b/src/research-literature.md index f1e85dcf..8767b01f 100644 --- a/src/research-literature.md +++ b/src/research-literature.md @@ -1,4 +1,4 @@ -## Research Literature +# Research Literature The following research papers cover specific aspects of Flix: diff --git a/src/sets-and-maps.md b/src/sets-and-maps.md index 05a0611e..43b59f6c 100644 --- a/src/sets-and-maps.md +++ b/src/sets-and-maps.md @@ -1,4 +1,4 @@ -## Sets and Maps +# Sets and Maps Flix has excellent support for (immutable) `Set`s and `Map` based on balanced trees; hence the elements of a `Set` and the keys of `Map` must implement the @@ -8,7 +8,7 @@ trees; hence the elements of a `Set` and the keys of `Map` must implement the > parallelize certain operations. Such operations are marked with > `@ParallelWhenPure` in the API docs. -### Sets +## Sets The empty set is written as: @@ -47,7 +47,7 @@ let sr = Set.union(s1, s2); Since `Set`s are `SemiGroup`s, we can also use the `++` operator and write `s1 ++ s2`. -### Maps +## Maps The empty map is written as: diff --git a/src/stratified-negation.md b/src/stratified-negation.md index 9f8044a0..8d4d2d34 100644 --- a/src/stratified-negation.md +++ b/src/stratified-negation.md @@ -1,4 +1,4 @@ -## Stratified Negation +# Stratified Negation Flix supports _stratified negation_ which allow restricted use of negation in rule bodies. diff --git a/src/string-interpolation.md b/src/string-interpolation.md index f59e8fe1..8a93a7e4 100644 --- a/src/string-interpolation.md +++ b/src/string-interpolation.md @@ -1,4 +1,4 @@ -## String Interpolation +# String Interpolation Flix strings support interpolation. Inside a string, the form `"${e}"` evaluates `e` to a value and converts it to a string using the `ToString` trait. For diff --git a/src/structs.md b/src/structs.md index b79d4a97..0b2eebf6 100644 --- a/src/structs.md +++ b/src/structs.md @@ -1,4 +1,4 @@ -## Structs +# Structs Flix supports mutable _scoped_ structs. A struct is a sequence of user-defined fields. Fields are immutable by default, but can be made mutable by marking them @@ -20,7 +20,7 @@ Flix supports three operations for working with structs: Each operation has an effect in the region of the struct. -### Declaring a Struct +## Declaring a Struct We can declare a struct as follows: @@ -41,7 +41,7 @@ region that the struct belongs to. Every struct must have a region type parameter and it must be the last in the type parameter list. -### Creating a Struct +## Creating a Struct We can create an instance of the `Person` struct as follows: @@ -65,7 +65,7 @@ specifies that we create a new instance of the `Person` struct in the region `rc`. We then specify the values of each field of the struct. All struct fields must be initialized immediately and explicitly. -### Reading and Writing Fields +## Reading and Writing Fields We can read and write fields of a struct using the field access operator `->`. For example: @@ -100,7 +100,7 @@ it, whereas the latter should have space on both sides. In summary: - `s->f`: is a struct field access of field `f` on struct `s`. - `x -> x`: is a function from formal parameter `x` to the variable expression `x`. -#### Field Visibility +### Field Visibility In Flix, the fields of a struct are only visible from within its companion module. We can think of this as a form of compiler-enforced encapsulation. @@ -163,7 +163,7 @@ mod Point { Thus access to the fields of struct is tightly controlled. -#### Immutable and Mutable Fields +### Immutable and Mutable Fields In Flix, every field of a struct is either immutable or mutable. A mutable field must be marked with the `mut` modifier. Otherwise the field is immutable by @@ -231,7 +231,7 @@ mod Book { Here we are not changing the field of the struct. We are changing the underlying mutable list. -### Recursive and Polymorphic Structs +## Recursive and Polymorphic Structs We can define a struct for a binary search tree that is recursive and polymorphic: diff --git a/src/tail-recursion.md b/src/tail-recursion.md index f409cd4c..77a69d20 100644 --- a/src/tail-recursion.md +++ b/src/tail-recursion.md @@ -1,4 +1,4 @@ -## Tail Recursion +# Tail Recursion In Flix, and in functional programming in general, iteration is expressed through [recursion](https://en.wikipedia.org/wiki/Recursion_(computer_science)). @@ -49,7 +49,7 @@ def main(): Unit \ IO = which is not the case in many other programming languages. -### Non-Tail Calls and StackOverflows +## Non-Tail Calls and StackOverflows While the Flix compiler _guarantees_ that tail calls cannot overflow the stack, the same is not true for function calls in non-tail positions. diff --git a/src/test-framework.md b/src/test-framework.md index b4454f1f..bb185682 100644 --- a/src/test-framework.md +++ b/src/test-framework.md @@ -1,4 +1,4 @@ -## Test Framework +# Test Framework Flix comes with a simple built-in test framework. diff --git a/src/tuples.md b/src/tuples.md index 238cdcbc..13352b90 100644 --- a/src/tuples.md +++ b/src/tuples.md @@ -1,4 +1,4 @@ -## Tuples +# Tuples A tuple is a product of values. The form of a tuple is `(exp1, ..., expn)`. diff --git a/src/type-aliases.md b/src/type-aliases.md index 1b38570e..40cc770c 100644 --- a/src/type-aliases.md +++ b/src/type-aliases.md @@ -1,4 +1,4 @@ -## Type Aliases +# Type Aliases Type aliases introduces a short-hand name for a type. diff --git a/src/type-ascriptions.md b/src/type-ascriptions.md index 08d32d18..cbc40f55 100644 --- a/src/type-ascriptions.md +++ b/src/type-ascriptions.md @@ -1,4 +1,4 @@ -## Type Ascriptions +# Type Ascriptions While Flix supports local type inference, it can sometimes be useful to annotate an expression or a let-binding with its type. We call such annotations *type @@ -18,7 +18,7 @@ It can also be placed on a let-binding without parentheses: ```flix let l: List[String] = "Hello" :: "World" :: Nil ``` -### Kind Ascriptions +## Kind Ascriptions Flix also supports kind ascriptions. Where a type ascription specifies the _type_ of an _expression_, a kind ascription specifies the _kind_ of a _type_. diff --git a/src/type-level-programming.md b/src/type-level-programming.md index 468a619f..20fcb5a7 100644 --- a/src/type-level-programming.md +++ b/src/type-level-programming.md @@ -1,11 +1,11 @@ -## Type-Level Programming +# Type-Level Programming > **Note:** This feature is experimental. Do not use in production. This section assumes prior familiarity with type-level programming and phantom types. -### Type-Level Booleans +## Type-Level Booleans A unique Flix feature is its support for _type-level Boolean formulas_. This means `true` and `false` are types, but also that formulas such as `x and (not @@ -22,7 +22,7 @@ We can use type-level Boolean formulas to statically enforce program invariants. We illustrate with a few examples: -#### Humans and Vampires +### Humans and Vampires ```flix /// diff --git a/src/type-match.md b/src/type-match.md index 12d80364..a4af2a63 100644 --- a/src/type-match.md +++ b/src/type-match.md @@ -1,4 +1,4 @@ -## Type Match +# Type Match Flix supports a type match construct that enables compile-time pattern matching on the type of a polymorphic value. diff --git a/src/unchecked-casts.md b/src/unchecked-casts.md index a5861787..c6a9edb0 100644 --- a/src/unchecked-casts.md +++ b/src/unchecked-casts.md @@ -1,8 +1,8 @@ -## Unchecked Type and Effect Casts +# Unchecked Type and Effect Casts Flix also supports _unchecked_ type and effect casts. -### Unchecked Type Casts +## Unchecked Type Casts An *unchecked type cast* instructs the compiler that an expression has a specific type. @@ -11,7 +11,7 @@ An *unchecked type cast* instructs the compiler that an expression has a specifi Flix programmers should normally never need to use an unchecked type cast. -#### Example: Safe Cast to a Super-Type +### Example: Safe Cast to a Super-Type The expression below casts a `String` to an `Object`: @@ -21,7 +21,7 @@ unchecked_cast("Hello World" as ##java.lang.Object) Note: It is safer to use the `checked_cast` expression. -#### Example: Safe Cast from Null to an Object-Type +### Example: Safe Cast from Null to an Object-Type The expression below casts the `null` value (of type `Null`) to `String`: @@ -31,7 +31,7 @@ unchecked_cast(null as ##java.lang.String) Note: It is safer to use the `checked_cast` expression. -#### Example: Unsafe Type Cast +### Example: Unsafe Type Cast The expression below contains an illegal cast and triggers a `ClassCastException` at runtime: @@ -40,7 +40,7 @@ The expression below contains an illegal cast and triggers a unchecked_cast((123, 456) as ##java.lang.Integer) ``` -### Effect Casts +## Effect Casts An *unchecked effect cast* instructs the compiler that an expression has a specific effect. @@ -50,7 +50,7 @@ specific effect. Flix programmers should normally never need to use an unchecked effect cast. -#### Example: Unsafe Effect Cast +### Example: Unsafe Effect Cast We can pretend an impure expression is pure: diff --git a/src/using-modules.md b/src/using-modules.md index 5d772e5e..8714879f 100644 --- a/src/using-modules.md +++ b/src/using-modules.md @@ -1,4 +1,4 @@ -## Using Modules +# Using Modules As we have already seen, the `use` construct brings members of a module into local scope. @@ -33,7 +33,7 @@ use A.B.Hue use A.B.isWarm ``` -### All Kinds of Uses +## All Kinds of Uses Flix supports several kinds of uses, including: @@ -44,7 +44,7 @@ Flix supports several kinds of uses, including: > **Note:** Flix does not support wildcard. -### Where can Uses Occur? +## Where can Uses Occur? Flix supports uses in two places: @@ -89,7 +89,7 @@ mod A { Note the use of semicolons when inside an expression. -### Default Uses +## Default Uses In Flix, a few built-in constructors are always in scope: diff --git a/src/videos.md b/src/videos.md index dfca7ac3..b55b788d 100644 --- a/src/videos.md +++ b/src/videos.md @@ -1,14 +1,14 @@ -## Videos +# Videos A collection of videos about Flix. -### Industry Talks +## Industry Talks - Magnus Madsen @ LambdaDays 2025: [An Introduction to Effectful Programming in Flix](https://www.youtube.com/watch?v=DHB4SvB7g84) ([slides](https://flix.dev/talks/lambdadays2025.pdf)) - Magnus Madsen @ Devoxx Greece 2025: [Effectful Programming in the Flix Programming Language](https://www.youtube.com/watch?v=o7-JWY0uLmc) ([slides](https://flix.dev/talks/devoxx2025.pdf)) - Magnus Madsen @ Goto 2023: [An Introduction to Functional Imperative Programming in Flix](https://www.youtube.com/watch?v=2LSOqikNqxM) -### Research Talks +## Research Talks - Matthew Lutze @ PLDI 2024: [Associated Effects: Flexible Abstractions for Effectful Programming](https://www.youtube.com/watch?v=HoJaLJEPXW8) - Matthew Lutze @ ICFP 2023:[With or Without You: Programming with Effect Exclusion](https://www.youtube.com/watch?v=IyLNJh4Eq0c) diff --git a/src/vscode.md b/src/vscode.md index 39e1c278..cedca166 100644 --- a/src/vscode.md +++ b/src/vscode.md @@ -1,4 +1,4 @@ -## Visual Studio Code Extension +# Visual Studio Code Extension Flix comes with [a fully-featured Visual Studio Code Extension](https://marketplace.visualstudio.com/items?itemName=flix.flix): @@ -9,7 +9,7 @@ messages) are always 1:1 with the real Flix programming language. Flix also comes with an (optional) Visual Studio Code color theme called "Flixify Dark". -### Features +## Features * __Semantic Syntax Highlighting__ - Code highlighting for *.flix files. This work best with the [official vscode theme](https://marketplace.visualstudio.com/items?itemName=flix.flixify-dark). @@ -62,7 +62,7 @@ Flix also comes with an (optional) Visual Studio Code color theme called "Flixif * __Semantic Tokens__ - Additional code highlighting hints provided by the compiler. -### Known Limitations +## Known Limitations - There is a known issue with PowerShell and using file names that contain special characters. We recommend that Flix source files are given only ASCII