diff --git a/src/lib/indexExamples.js b/src/lib/indexExamples.js index ab946ad..171c3f5 100644 --- a/src/lib/indexExamples.js +++ b/src/lib/indexExamples.js @@ -100,6 +100,24 @@ def main(): Unit \\ IO = resume(dt.getHour()) }`; +export const libraryEffectsExample = `use Fs.FileRead +use Sys.Env +use Time.Clock +use Time.TimeUnit + +/// The \`Clock\`, \`Env\`, \`FileRead\`, and \`Logger\` +/// effects all have default handlers, hence \`main\` +/// requires no explicit handlers. +def main(): Unit \\ { Clock, Env, FileRead, Logger } = + let ts = Clock.currentTime(TimeUnit.Milliseconds); + let os = Env.getOsName(); + Logger.info("Timestamp: \${ts}"); + Logger.info("Operating System: \${os}"); + match FileRead.read("data.txt") { + case Ok(content) => Logger.info("Read: \${content}") + case Err(err) => Logger.warn("Error: \${err}") + }`; + export const regionExample = `/// /// We can implement a *pure* \`sort\` function which /// internally converts an immutable list to an array, @@ -125,6 +143,25 @@ def toString(l: List[a]): String with ToString[a] = StringBuilder.toString(sb) }`; +export const structsExample = `struct Person[r] { + name: String, + mut age: Int32 +} + +mod Person { + /// Creates a fresh \`Person\` in the region \`rc\`. + pub def mkPerson(name: String, rc: Region[r]): Person[r] \\ r = + new Person @ rc { name = name, age = 0 } + + /// Increments the age of the given person \`p\`. + pub def birthday(p: Person[r]): Unit \\ r = + p->age = p->age + 1 + + /// Returns a description of the given person \`p\`. + pub def describe(p: Person[r]): String \\ r = + "\${p->name} is \${p->age} years old" +}`; + export const purityReflectionExample = `/// /// We can inspect the purity of a function argument. /// @@ -264,6 +301,19 @@ def main(): Unit \\ IO = println("Unable to write file") }`; +export const terminationExample = `enum Tree[a] { + case Leaf(a) + case Node(Tree[a], Tree[a]) +} + +/// The compiler verifies that \`size\` is structurally +/// recursive and hence terminates on all inputs. +@Terminates +def size(t: Tree[Int32]): Int32 = match t { + case Tree.Leaf(_) => 1 + case Tree.Node(l, r) => size(l) + size(r) +}`; + export const datalogExample = `def reachable(g: List[(String, Int32, String)], minSpeed: Int32): List[(String, String)] = let facts = inject g into Road/3; let rules = #{ diff --git a/src/pages/index.astro b/src/pages/index.astro index 73c58e4..e056be6 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -9,7 +9,9 @@ import { purityExample, polyEffectsExample, effectsExample, + libraryEffectsExample, regionExample, + structsExample, purityReflectionExample, parallelismExample, concurrencyExample, @@ -20,6 +22,7 @@ import { monadicForExample, applicativeForExample, javaInteropExample, + terminationExample, datalogExample, latticeExample, } from "../lib/indexExamples.js"; @@ -87,6 +90,9 @@ const vscodeSlides = [
- For example, the program on the right expresses a greeting function that is pure modulo the current time of the day. In main
+ The Flix Standard Library comes with a rich collection of
+ built-in effects, including Clock, Console, Env, FileSystem, Http, Logger, Process, and Random.
+
+ Every library effect has a default handler, hence programs can + use them without any handler boilerplate. +
++ Library effects support composable middleware: HTTP requests can + be configured with retries and circuit breakers, and the + filesystem can be sandboxed, made read-only, or replaced with an + in-memory implementation, e.g. for testing. +
+
+ Flix supports mutable structs. Fields are immutable by
+ default, but can be marked with the mut modifier.
+ Like all mutable memory in Flix, every struct belongs to a
+ region.
+
+ Struct fields are unboxed, i.e. primitive fields do not require + indirection. This makes structs a memory efficient building + block for higher-level data structures, e.g. mutable lists, + stacks, and queues. +
++ The fields of a struct are only visible from within its + companion module, providing compiler-enforced encapsulation. +
+
+ Flix supports the @Terminates annotation, which
+ asks the compiler to verify that a function is structurally
+ recursive — and hence guaranteed to terminate on all
+ inputs.
+
+ The compiler checks that every recursive call is on a strict + substructure of a formal parameter. The check supports tree + recursion, functions with multiple parameters, local + definitions, and higher-order functions. +
+