Fanak is a functional programming language that compiles to CIL (.NET). It has
algebraic data types with pattern matching, typeclasses, higher-order functions
and a small effectful standard library.
In LiveCodes, Fanak compiles and runs entirely in the browser: the Fanak
compiler and a .NET WebAssembly runtime (Blazor WebAssembly) are fetched from
the Fanak project, the program's assembly is emitted in memory, and the result
runs in the page.
Usage
Demo:
show code
- JS
- TS
- React
- Vue
- Svelte
- Solid
- Preact
- Web Components
import { createPlayground } from 'livecodes';
const options = {
"config": {
"activeEditor": "script",
"script": {
"language": "fanak",
"content": "import std;\n\nUnit main() {\n List<int> xs = List.empty<int>().add(1).add(2).add(3);\n List<int> tens = xs.iter().map((int x) => x * 10).toList();\n runUnit(println(tens));\n}"
},
"mode": "simple",
"editor": "auto",
"tools": {
"status": "full"
}
}
};
createPlayground('#container', options);
import { createPlayground, type EmbedOptions } from 'livecodes';
const options: EmbedOptions = {
"config": {
"activeEditor": "script",
"script": {
"language": "fanak",
"content": "import std;\n\nUnit main() {\n List<int> xs = List.empty<int>().add(1).add(2).add(3);\n List<int> tens = xs.iter().map((int x) => x * 10).toList();\n runUnit(println(tens));\n}"
},
"mode": "simple",
"editor": "auto",
"tools": {
"status": "full"
}
}
};
createPlayground('#container', options);
import LiveCodes from 'livecodes/react';
export default function App() {
const options = {
"config": {
"activeEditor": "script",
"script": {
"language": "fanak",
"content": "import std;\n\nUnit main() {\n List<int> xs = List.empty<int>().add(1).add(2).add(3);\n List<int> tens = xs.iter().map((int x) => x * 10).toList();\n runUnit(println(tens));\n}"
},
"mode": "simple",
"editor": "auto",
"tools": {
"status": "full"
}
}
};
return (<LiveCodes {...options} />);
}
<script setup>
import LiveCodes from "livecodes/vue";
const options = {
"config": {
"activeEditor": "script",
"script": {
"language": "fanak",
"content": "import std;\n\nUnit main() {\n List<int> xs = List.empty<int>().add(1).add(2).add(3);\n List<int> tens = xs.iter().map((int x) => x * 10).toList();\n runUnit(println(tens));\n}"
},
"mode": "simple",
"editor": "auto",
"tools": {
"status": "full"
}
}
};
</script>
<template>
<LiveCodes v-bind="options" />
</template>
<script>
import LiveCodes from 'livecodes/svelte';
const options = {
"config": {
"activeEditor": "script",
"script": {
"language": "fanak",
"content": "import std;\n\nUnit main() {\n List<int> xs = List.empty<int>().add(1).add(2).add(3);\n List<int> tens = xs.iter().map((int x) => x * 10).toList();\n runUnit(println(tens));\n}"
},
"mode": "simple",
"editor": "auto",
"tools": {
"status": "full"
}
}
};
</script>
<LiveCodes {...options} />
import LiveCodes from 'livecodes/solid';
export default function App() {
const options = {
"config": {
"activeEditor": "script",
"script": {
"language": "fanak",
"content": "import std;\n\nUnit main() {\n List<int> xs = List.empty<int>().add(1).add(2).add(3);\n List<int> tens = xs.iter().map((int x) => x * 10).toList();\n runUnit(println(tens));\n}"
},
"mode": "simple",
"editor": "auto",
"tools": {
"status": "full"
}
}
};
return (<LiveCodes {...options} />);
}
import LiveCodes from 'livecodes/preact';
export default function App() {
const options = {
"config": {
"activeEditor": "script",
"script": {
"language": "fanak",
"content": "import std;\n\nUnit main() {\n List<int> xs = List.empty<int>().add(1).add(2).add(3);\n List<int> tens = xs.iter().map((int x) => x * 10).toList();\n runUnit(println(tens));\n}"
},
"mode": "simple",
"editor": "auto",
"tools": {
"status": "full"
}
}
};
return (<LiveCodes {...options} />);
}
<live-codes></live-codes>
<script type="module">
import "livecodes/web-components";
const playground = document.querySelector("live-codes");
playground.config = {
"activeEditor": "script",
"script": {
"language": "fanak",
"content": "import std;\n\nUnit main() {\n List<int> xs = List.empty<int>().add(1).add(2).add(3);\n List<int> tens = xs.iter().map((int x) => x * 10).toList();\n runUnit(println(tens));\n}"
},
"mode": "simple",
"editor": "auto",
"tools": {
"status": "full"
}
};
</script>
Language Info
Name
fanak
Aliases / Extensions
fnk, fanak
Editor
script
Compiler
The Fanak compiler and .NET WebAssembly runtime (Blazor WebAssembly), fetched
from the Fanak project and run entirely
in the browser. There is no server round-trip; the first run downloads the
runtime and can take a moment.
The prelude is implicit in every file. The standard library is opt-in with
import std;.
Version
0.1.0
In the Monaco editor, formatting is provided by the Fanak language service
(compiler-backed, using the Fanak compiler's own formatter). It is not
available in the CodeMirror or CodeJar editors.
Communication with JavaScript
The Fanak program runs in the context of the result page. A few helpers are
available on the browser global livecodes.fanak object:
livecodes.fanak.loaded: a promise that resolves when the compiler and the
program have finished running.
livecodes.fanak.output: the program's standard output (a string), or null.
livecodes.fanak.error: the program's error output (a string), or null.
livecodes.fanak.exitCode: 0 on success, 1 on error.
livecodes.fanak.run: re-runs the program and returns a promise resolving to an
object with output, error and exitCode. (It accepts an input argument
for host parity, but Fanak has no standard-input primitive yet, so it is
currently ignored.)
Example:
show code
- JS
- TS
- React
- Vue
- Svelte
- Solid
- Preact
- Web Components
import { createPlayground } from 'livecodes';
const options = {
"template": "fanak",
"params": {
"activeEditor": "markup"
}
};
createPlayground('#container', options);
import { createPlayground, type EmbedOptions } from 'livecodes';
const options: EmbedOptions = {
"template": "fanak",
"params": {
"activeEditor": "markup"
}
};
createPlayground('#container', options);
import LiveCodes from 'livecodes/react';
export default function App() {
const options = {
"template": "fanak",
"params": {
"activeEditor": "markup"
}
};
return (<LiveCodes {...options} />);
}
<script setup>
import LiveCodes from "livecodes/vue";
const options = {
"template": "fanak",
"params": {
"activeEditor": "markup"
}
};
</script>
<template>
<LiveCodes v-bind="options" />
</template>
<script>
import LiveCodes from 'livecodes/svelte';
const options = {
"template": "fanak",
"params": {
"activeEditor": "markup"
}
};
</script>
<LiveCodes {...options} />
import LiveCodes from 'livecodes/solid';
export default function App() {
const options = {
"template": "fanak",
"params": {
"activeEditor": "markup"
}
};
return (<LiveCodes {...options} />);
}
import LiveCodes from 'livecodes/preact';
export default function App() {
const options = {
"template": "fanak",
"params": {
"activeEditor": "markup"
}
};
return (<LiveCodes {...options} />);
}
<live-codes
template="fanak"></live-codes>
<script type="module">
import "livecodes/web-components";
const playground = document.querySelector("live-codes");
playground.params = {
"activeEditor": "markup"
};
</script>
Live Reload
By default, new code changes are sent to the result page for re-evaluation
without a full page reload, avoiding the need to reinitialize the compiler.
Example Usage
import std;
Unit main() {
// Options, lambdas and pattern matching
Option<int> answer = Some(6 * 7);
runUnit(println(answer.getOr(0))); // 42
}
Starter Template
https://livecodes.io/?template=fanak
Links