yeet skills i don't really use

Amolith created

Change summary

README.md                                                           |   70 
skills/managing-and-navigating-worktrees/SKILL.md                   |  105 
skills/managing-and-navigating-worktrees/refs/adding.md             |   70 
skills/managing-and-navigating-worktrees/refs/cloning.md            |   57 
skills/managing-and-navigating-worktrees/refs/config.md             |   47 
skills/managing-and-navigating-worktrees/refs/converting.md         |   39 
skills/managing-and-navigating-worktrees/refs/installation.md       |    4 
skills/managing-and-navigating-worktrees/refs/new-project.md        |   32 
skills/resuming-work-through-lunatask/SKILL.md                      |   51 
skills/resuming-work-through-lunatask/references/cli.md             |   45 
skills/resuming-work-through-lunatask/references/installing-lune.md |    1 
skills/writing-roc-lang/SKILL.md                                    |  125 
skills/writing-roc-lang/references/builtins-llms.md                 | 3405 
skills/writing-roc-lang/references/llms.md                          |  707 
skills/writing-roc-lang/references/scripting.md                     |   96 
15 files changed, 10 insertions(+), 4,844 deletions(-)

Detailed changes

README.md ๐Ÿ”—

@@ -58,7 +58,7 @@ token count, plus overall metadata usage. I've used and tested them most with
 - [handling-customer-data](skills/handling-customer-data/SKILL.md): Queries
   customer data responsiblyโ€”the agent answers questions about the data without
   ever seeing it directly.
-- [humanizer](skills/humanizer/SKILL.md): Removes AI-generated patterns from
+- [humanize](skills/humanize/SKILL.md): Removes AI-generated patterns from
   text like promotional fluff, weasel words, and mechanical sentence structures.
   Based on Wikipedia's AI Cleanup research. Originally from [blader/humanizer].
 - [ideating-with-bdd](skills/ideating-with-bdd/SKILL.md): Guides collaborative
@@ -77,9 +77,6 @@ token count, plus overall metadata usage. I've used and tested them most with
   and updates AUR packages following Arch packaging standards. Covers PKGBUILDs
   for source, `-bin`, and `-git` package types, checksums with `updpkgsums`,
   linting with `namcap`, and `.SRCINFO` generation.
-- [managing-and-navigating-worktrees](skills/managing-and-navigating-worktrees/SKILL.md):
-  Manages git worktrees using [wt] with a bare repository structure. Each branch
-  lives in its own sibling directory. Requires [wt], git, and [gum].
 - [monitoring-with-munin](skills/monitoring-with-munin/SKILL.md): Deploys and
   manages Munin monitoring across servers. Sets up munin-node on hosts, writes
   plugins, configures masters, and handles alerts.
@@ -93,8 +90,6 @@ token count, plus overall metadata usage. I've used and tested them most with
   AI research subagents via [rumilo] for web search and repository exploration.
   Research topics, look up library usage, or explore external codebases without
   filling the main context window.
-- [resuming-work-through-lunatask](skills/resuming-work-through-lunatask/SKILL.md):
-  Resumes deferred work from [Lunatask] handoff notes via [lune].
 - [scripting-with-go](skills/scripting-with-go/SKILL.md): Creates executable Go
   scripts using a shell trick (not a true shebang). For automation and tooling
   outside of Go projects.
@@ -107,15 +102,9 @@ token count, plus overall metadata usage. I've used and tested them most with
 - [using-exe-dev](skills/using-exe-dev/SKILL.md): Guides working with [exe.dev]
   VMs, which provide Linux VMs with persistent disks, instant HTTPS, and
   built-in auth via SSH.
-- [using-goji](skills/using-goji/SKILL.md): Manages goji workspaces and zmx
-  sessions for git worktrees and jj workspaces. Covers conversion, creation,
-  listing, attaching, removal, JSON output, and safe temp-repo testing.
 - [using-jujutsu](skills/using-jujutsu/SKILL.md): Guides [jujutsu] (jj)
   workflows, covering commit selection, change creation, diff reading, and
   common pitfalls that trip up agents.
-- [using-silverbullet](skills/using-silverbullet/SKILL.md): Manages notes in
-  [SilverBullet] via the CLI and Space Lua. Covers searching, reading, writing,
-  and editing pages, plus journal and task workflows.
 - [working-with-zmx](skills/working-with-zmx/SKILL.md): Manages persistent
   terminal sessions for background processes, dev servers, and long-running tasks.
   Creates sessions, runs commands detached, checks output, and writes files into
@@ -123,9 +112,6 @@ token count, plus overall metadata usage. I've used and tested them most with
 - [writing-git-tags](skills/writing-git-tags/SKILL.md): Generates git tag
   annotations from commit history following Semantic Versioning and Conventional
   Commits via [git-format].
-- [writing-roc-lang](skills/writing-roc-lang/SKILL.md): Writes Roc code with
-  strong static types, helpful compiler errors, and functional programming.
-  Covers both full applications and one-off scripts.
 - [writing-rust](skills/writing-rust/SKILL.md): Writes idiomatic Rust with
   strict quality gates: `cargo fmt`, `clippy -- -D warnings`, and required
   tests. Enforces `thiserror` for libs, `anyhow` for apps, warns against common
@@ -141,10 +127,8 @@ token count, plus overall metadata usage. I've used and tested them most with
 [rumilo]: https://git.secluded.site/rumilo
 [synu]: https://git.secluded.site/synu
 [wt]: https://git.secluded.site/wt
-[gum]: https://github.com/charmbracelet/gum
 [exe.dev]: https://exe.dev
 [jujutsu]: https://jj-vcs.github.io/jj/latest/
-[SilverBullet]: https://silverbullet.md
 
 ## Installation
 
@@ -429,15 +413,6 @@ Token breakdown:
   โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
   Total:        2626 tokens
 
-=== managing-and-navigating-worktrees ===
-
-Token breakdown:
-  Name:           11 tokens
-  Description:    60 tokens
-  Body:          703 tokens (96 lines)
-  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
-  Total:         774 tokens
-
 === monitoring-with-munin ===
 
 Token breakdown:
@@ -482,18 +457,6 @@ Token breakdown:
   โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
   Total:        1287 tokens
 
-=== resuming-work-through-lunatask ===
-
-Token breakdown:
-  Name:           12 tokens
-  Description:    44 tokens
-  Body:          466 tokens (42 lines)
-  References:
-    cli.md                                     195 tokens
-    installing-lune.md                          65 tokens
-  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
-  Total:         782 tokens
-
 === scripting-with-go ===
 
 Token breakdown:
@@ -562,19 +525,6 @@ Token breakdown:
   โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
   Total:         888 tokens
 
-=== writing-roc-lang ===
-
-Token breakdown:
-  Name:            8 tokens
-  Description:    53 tokens
-  Body:          693 tokens (117 lines)
-  References:
-    builtins-llms.md                         25216 tokens
-    llms.md                                   4253 tokens
-    scripting.md                               614 tokens
-  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
-  Total:       30837 tokens
-
 === writing-rust ===
 
 Token breakdown:
@@ -590,18 +540,18 @@ Token breakdown:
 SUMMARY
 ============================================================
 
-Skills: 31
-Metadata: 2023 tokens
-Combined bodies: 31528 tokens
-Overall: 90092 tokens
+Skills: 28
+Metadata: 1835 tokens
+Combined bodies: 29666 tokens
+Overall: 57699 tokens
 Validation errors: 0
 
 Largest skills (by total tokens):
-  1. writing-roc-lang                         30837 tokens
-  2. ast-grep                                  5363 tokens
-  3. humanize                                  5003 tokens
-  4. frontend-accessibility                    4759 tokens
-  5. authoring-skills                          3834 tokens
+  1. ast-grep                                  5363 tokens
+  2. humanize                                  5003 tokens
+  3. frontend-accessibility                    4759 tokens
+  4. authoring-skills                          3834 tokens
+  5. notifying-through-ntfy                    3355 tokens
 ```
 
 ---

skills/managing-and-navigating-worktrees/SKILL.md ๐Ÿ”—

@@ -1,105 +0,0 @@
----
-name: managing-and-navigating-worktrees
-description: Manages git worktrees and repos using the wt CLI. Use when cloning or creating new repos, adding worktrees, switching branches or branches, when the user mentions wt or worktrees. If you need to clone and whether to use worktrees/this skill is unclear, ask the user.
-compatibility: Requires wt CLI, git, and gum
-license: LicenseRef-MutuaL-1.2
-metadata:
-  author: Amolith <amolith@secluded.site>
----
-
-# Managing Git Worktrees with wt
-
-`wt` manages git repositories using a bare repository structure:
-
-- `.bare/` contains the actual git repository
-- `.git` is a file pointing to `.bare/`
-- Each branch lives in its own directory as sibling worktrees
-
-## Quick Reference
-
-| Command         | Purpose                                 |
-| --------------- | --------------------------------------- |
-| `wt c <url>`    | Clone repo into bare structure          |
-| `wt n <name>`   | Create new project                      |
-| `wt a <branch>` | Add worktree for branch                 |
-| `wt r <branch>` | Remove worktree                         |
-| `wt l`          | List worktrees with status              |
-| `wt f`          | Fetch all remotes                       |
-| `wt init`       | Convert existing repo to bare structure |
-
-## Common Workflows
-
-### Start a new project
-
-```bash
-wt n my-project --remote github
-cd my-project/main
-```
-
-### Clone and start working
-
-```bash
-wt c https://github.com/user/repo.git
-cd repo/main
-```
-
-### Create feature branch
-
-From inside any worktree:
-
-```bash
-wt a feature/new-thing -b main
-cd ../feature/new-thing
-```
-
-### Switch between branches
-
-Just `cd` to the worktree directoryโ€”no checkout needed:
-
-```bash
-cd ../main        # switch to main
-cd ../feature/x   # switch to feature branch
-```
-
-If the branch already exists in a remote, but doesn't yet have a local worktree, use `wt a branch` to fetch and create it.
-
-### Clean up finished work
-
-```bash
-wt r feature/old -b    # remove worktree AND delete branch
-```
-
-### Convert existing repo
-
-```bash
-cd existing-repo
-wt init              # --dry-run to preview, -y to skip prompt
-```
-
-## Command Details
-
-- **New project**: See [refs/new-project.md](refs/new-project.md) for remote templates
-- **Cloning**: See [refs/cloning.md](refs/cloning.md) for remote configuration and own vs contributor mode
-- **Adding worktrees**: See [refs/adding.md](refs/adding.md) for hooks and branch creation
-- **Converting repos**: See [refs/converting.md](refs/converting.md) for `wt init` details
-- **Config files**: See [refs/config.md](refs/config.md) for `.wt.lua` and global config
-
-If you lack context, READ THESE instead of immediately trying to use `wt` or relying on `-h` output. The refs might just give you the answer without you needing to fumble and find them.
-
-## Working Directory
-
-`wt` works from either the project root or any worktree. Run `wt l` to determine context:
-
-- **In a worktree**: Current worktree shows `./` in the Path column
-- **At project root**: All paths are relative names (e.g., `main`, `feature/foo`)
-
-From project root, `wt a` skips hooks. From a worktree, hooks trigger.
-
-## Key Behaviors
-
-1. **Hooks only trigger from worktrees**: Running `wt a` from project root skips hooks
-2. **Branch paths**: `feature/foo` becomes `project/feature/foo` (nested) or `project_feature_foo` (flat, if configured)
-
----
-
-See [refs/installation.md](refs/installation.md) if you try to use `wt` and it's not available. Do not reference this file until and unless you invoke `wt` and get some kind of command not found error.

skills/managing-and-navigating-worktrees/refs/adding.md ๐Ÿ”—

@@ -1,70 +0,0 @@
-# Adding Worktrees
-
-## Basic Usage
-
-```bash
-wt a <branch> [-b [<start-point>]]
-```
-
-## Examples
-
-```bash
-wt a main                    # checkout existing branch
-wt a feature/new -b          # create new branch from HEAD
-wt a feature/new -b main     # create new branch from main
-wt a feature/new -b v1.0.0   # create new branch from tag
-```
-
-## Hooks
-
-When `wt a` runs **from inside an existing worktree**, hooks from `.wt.lua` are applied to the new worktree.
-
-Running from project root skips hooks with a warning.
-
-### Hook Types
-
-| Hook      | Purpose                                  |
-| --------- | ---------------------------------------- |
-| `copy`    | Copy files from source worktree          |
-| `symlink` | Create symlinks to source worktree files |
-| `run`     | Execute shell commands in new worktree   |
-
-### Example `.wt.lua`
-
-```lua
-return {
-    hooks = {
-        copy = {"Makefile", "*.mk"},
-        symlink = {".env", "config.toml", "node_modules"},
-        run = {"make setup", "npm install"}
-    }
-}
-```
-
-### Hook Permissions
-
-First time hooks run in a project, `wt` prompts for permission via `gum confirm`. Permissions stored in `~/.local/share/wt/hook-dirs.lua`.
-
-## Branch Resolution
-
-When adding without `-b`:
-
-1. Checks local branches
-2. Checks all remotes
-3. Fails if branch exists on multiple remotes (ambiguous)
-
-## Path Styles
-
-Configured in `~/.config/wt/config.lua`:
-
-| Style              | Example Branch | Result Path           |
-| ------------------ | -------------- | --------------------- |
-| `nested` (default) | `feature/foo`  | `project/feature/foo` |
-| `flat`             | `feature/foo`  | `project_feature_foo` |
-
-```lua
-return {
-    branch_path_style = "flat",
-    flat_separator = "_"
-}
-```

skills/managing-and-navigating-worktrees/refs/cloning.md ๐Ÿ”—

@@ -1,57 +0,0 @@
-# Cloning Repositories
-
-## Basic Usage
-
-```bash
-wt c <url> [--remote name]... [--own]
-```
-
-## Remote Configuration
-
-Configure remotes in `~/.config/wt/config.lua`:
-
-```lua
-return {
-    remotes = {
-        github = "git@github.com:myuser/${project}.git",
-        gitlab = "git@gitlab.com:myuser/${project}.git"
-    },
-    default_remotes = {"github"}  -- or "prompt" to ask each time
-}
-```
-
-Use `--remote` to add configured remotes:
-
-```bash
-wt c https://github.com/user/repo.git --remote github --remote gitlab
-```
-
-## Contributor vs Own Mode
-
-### Contributor mode (default)
-
-For contributing to others' projects:
-
-- `origin` renamed to `upstream`
-- Selected remotes added from config
-
-```bash
-wt c https://github.com/user/repo.git --remote github
-# origin โ†’ upstream
-# github remote added pointing to your fork
-```
-
-### Own mode (`--own`)
-
-For your own projects:
-
-- First selected remote becomes `origin`
-- Additional remotes added as mirrors
-
-```bash
-wt c git@github.com:me/my-project.git --remote github --remote gitlab --own
-# github โ†’ origin
-# gitlab added as mirror
-```
-
-

skills/managing-and-navigating-worktrees/refs/config.md ๐Ÿ”—

@@ -1,47 +0,0 @@
-# Configuration
-
-## Global Config
-
-Location: `~/.config/wt/config.lua`
-
-```lua
-return {
-    -- Path style for worktree directories
-    branch_path_style = "nested",  -- or "flat"
-    flat_separator = "_",          -- separator for flat style
-
-    -- Remote URL templates (${project} is substituted)
-    remotes = {
-        github = "git@github.com:myuser/${project}.git",
-        gitlab = "git@gitlab.com:myuser/${project}.git",
-        codeberg = "git@codeberg.org:myuser/${project}.git"
-    },
-
-    -- Which remotes to add by default
-    -- "prompt" = ask each time
-    -- {"github", "gitlab"} = use these automatically
-    -- nil = prompt if remotes exist
-    default_remotes = "prompt"
-}
-```
-
-## Project Config
-
-Location: `.wt.lua` in project root (alongside `.bare/`)
-
-```lua
-return {
-    hooks = {
-        -- Files to copy from source worktree
-        copy = {"Makefile", "*.mk", ".tool-versions"},
-
-        -- Files to symlink from source worktree
-        symlink = {".env", ".env.local", "node_modules"},
-
-        -- Commands to run in new worktree
-        run = {"make deps", "npm install"}
-    }
-}
-```
-
-

skills/managing-and-navigating-worktrees/refs/converting.md ๐Ÿ”—

@@ -1,39 +0,0 @@
-# Converting Existing Repos
-
-```bash
-wt init [--dry-run] [-y]
-```
-
-Converts a standard git repository to bare worktree structure.
-
-## Options
-
-| Flag | Purpose |
-|------|---------|
-| `--dry-run` | Show what would happen without making changes |
-| `-y` | Skip confirmation prompt |
-
-## What It Does
-
-1. Moves `.git/` to `.bare/`
-2. Creates `.git` file pointing to `.bare/`
-3. Creates worktree for current branch
-4. Copies untracked/ignored files to worktree (preserves `.env`, build artifacts, etc.)
-5. Removes orphaned files from project root
-
-## Example
-
-```bash
-cd ~/repos/existing-project
-wt init --dry-run    # preview changes
-wt init -y           # convert without prompting
-```
-
-After conversion:
-
-```
-existing-project/
-โ”œโ”€โ”€ .bare/           # was .git/
-โ”œโ”€โ”€ .git             # file pointing to .bare/
-โ””โ”€โ”€ main/            # worktree with your files
-```

skills/managing-and-navigating-worktrees/refs/new-project.md ๐Ÿ”—

@@ -1,32 +0,0 @@
-# Creating New Projects
-
-```bash
-wt n <project-name> [--remote name]...
-```
-
-Creates a fresh project with bare worktree structure:
-
-```
-my-project/
-โ”œโ”€โ”€ .bare/          # git repository
-โ”œโ”€โ”€ .git            # file pointing to .bare/
-โ””โ”€โ”€ main/           # default worktree
-```
-
-## With Remotes
-
-Add configured remotes from `~/.config/wt/config.lua`:
-
-```bash
-wt n my-project --remote github --remote gitlab
-```
-
-Remotes use URL templates with `${project}` substituted:
-
-```lua
-remotes = {
-    github = "git@github.com:myuser/${project}.git"
-}
-```
-
-Results in remote URL `git@github.com:myuser/my-project.git`.

skills/resuming-work-through-lunatask/SKILL.md ๐Ÿ”—

@@ -1,51 +0,0 @@
----
-name: resuming-work-through-lunatask
-description: Resumes previously deferred work from Lunatask. Use when user pastes a task note, shares a lunatask:// deep link, says "let's pick this up", or references continuing earlier work.
-compatibility: Requires Lunatask MCP or CLI tools
-license: LicenseRef-MutuaL-1.2
-metadata:
-  author: Amolith <amolith@secluded.site>
----
-
-## Purpose
-
-Handoff notes are **navigation aids**, not solutions. They point you toward relevant code and context, but the codebase may have changed since the handoff was written. Your job is to explore the current state and form your own understanding.
-
-## Before acting
-
-1. Read the actual files: entry points in the handoff tell you where to look, but always read the current source. Any code snippets in the handoff may be stale.
-2. Verify the plan still applies: check that the goal is still relevant and the suggested approach still makes sense given the current code.
-3. If present, follow the references: external links, commits, and docs in the handoff were included for a reason. Skim them for context.
-
-## If the code has diverged
-
-If you find significant differences between what the handoff describes and what the code actually looks like:
-
-- Stop
-- Summarize what changed
-- Wait for user input before proceeding
-
-Don't try to reconcile the handoff with reality on your own. The user may have context about why things changed.
-
-## Surfacing tech debt
-
-While working, you may notice code smells, outdated patterns, missing tests, or other improvement opportunities related _or unrelated_ to the current task. We might also intentionally introduce tech debt, aware of the trade-offs. Don't let these observations or introductions disappear with the session.
-
-- Mention them briefly to the user before or after completing the main work
-- Offer to capture them as standalone task(s) so the user can pick up or hand off to another agent later. Even as standalone tasks, make sure to include enough context that another agent could pick it up.
-
-Don't derail the primary task, but don't let useful observations vanish either.
-
-## Workflow
-
-When you begin working on the task, update its status according to the area's workflow. When finished, mark it `completed`.
-
-New tasks usually get status `later`, then `in-progress`, then lastly `completed`. Different workflows might have other stages, but those are core.
-
-## Working around a Lunatask bug
-
-At the very very end of task notes or note contents, include `[editor_v2]::` on its own line.
-
----
-
-If `lunatask` or `lune` MCP tools are unavailable, see [cli.md](references/cli.md). If the CLI is also unavailable, see [installing-lune.md](references/installing-lune.md).

skills/resuming-work-through-lunatask/references/cli.md ๐Ÿ”—

@@ -1,45 +0,0 @@
-When MCP tools are unavailable, use `lune` CLI. Destructive actions are interactive unless supplied `--force`.
-
-**Try `lune` directly first**โ€”it integrates with the system keyring. Only fall back to the `resolving-secrets` skill if the user isn't using keyring-based credential storage.
-
-## Showing task details
-
-```bash
-lune task show ID
-```
-
-Accepts UUID or `lunatask://` deep link. Due to encryption, name/note aren't visibleโ€”only metadata.
-
-## Updating status
-
-```bash
-lune task update ID -s STATUS
-```
-
-Valid statuses depend on the area's workflow (see `lune area list`).
-
-## Updating notes
-
-```bash
-lune task update ID -n "$(cat <<'EOF'
-Intro paragraph
-
-# Section
-
-Content
-
----
-
-Appended content
-
-EOF
-)"
-```
-
-Notes are replaced entirely, so reproduce original content when appending.
-
-## Marking complete
-
-```bash
-lune done ID
-```

skills/resuming-work-through-lunatask/references/installing-lune.md ๐Ÿ”—

@@ -1 +0,0 @@
-Read through https://git.secluded.site/lune/blob/main/README.md?raw=1 and help the user through installing/setting up either lune's CLI or MCP. The CLI with this skill would be more efficient for e.g. coding agents, but the MCP server is required for integrating with something like Home Assistant.

skills/writing-roc-lang/SKILL.md ๐Ÿ”—

@@ -1,125 +0,0 @@
----
-name: writing-roc-lang
-description: Writes Roc code with strong static types, helpful compiler errors, and functional programming. Use when the user wants Roc code, mentions Roc, functional programming with types, or needs .roc files. Covers both full applications and one-off Roc scripts with shebangs.
-license: LicenseRef-MutuaL-1.2
-metadata:
-  author: Amolith <amolith@secluded.site>
----
-
-Write code in Roc, a functional language with strong types, helpful compiler errors, and no runtime. Compiles to standalone binaries.
-
-## Reference documentation
-
-- **Language guide**: See [llms.md](references/llms.md) for comprehensive tutorial
-- **Standard library**: See [builtins-llms.md](references/builtins-llms.md) for all builtin modules
-- **CLI scripting**: See [scripting.md](references/scripting.md) for executable scripts with shebang
-
-## Language fundamentals
-
-### Functions
-
-```roc
-# Lambda syntax
-add = |a, b| a + b
-
-# Multi-line with indentation
-process = |text|
-    trimmed = Str.trim(text)
-    Str.to_upper(trimmed)
-
-# Type signatures (optional but helpful)
-greet : Str -> Str
-greet = |name| "Hello, ${name}!"
-```
-
-### Pattern matching
-
-```roc
-when value is
-    Ok(content) -> process(content)
-    Err(NotFound) -> "not found"
-    Err(_) -> "other error"
-```
-
-### Records and tags
-
-```roc
-# Records
-user = { name: "Alice", age: 30 }
-user.name  # Access field
-
-# Tags (algebraic data types)
-Color : [Red, Green, Blue, Custom Str]
-my_color = Custom("purple")
-```
-
-## Error handling
-
-Roc uses `Result` types, not exceptions. Use `?` to short-circuit:
-
-```roc
-main! = |_args|
-    content = File.read_utf8!(path)?  # Returns early if error
-    Stdout.line!("Success!")
-```
-
-Or explicit pattern matching:
-
-```roc
-when result is
-    Ok(content) -> Stdout.line!("Read: ${content}")
-    Err(err) -> Err(Exit(1, "Failed: ${Inspect.to_str(err)}"))
-```
-
-## Common patterns
-
-### Working with lists
-
-```roc
-numbers = [1, 2, 3, 4, 5]
-evens = List.keep_if(numbers, |n| n % 2 == 0)
-doubled = List.map(evens, |n| n * 2)
-sum = List.walk(doubled, 0, Num.add)
-```
-
-### String manipulation
-
-```roc
-text = Str.concat("Hello", " World")
-words = Str.split(text, " ")
-trimmed = Str.trim("  spaces  ")
-replaced = Str.replace_each(text, "World", "Roc")
-```
-
-## Code quality tools
-
-```bash
-roc format script.roc  # Auto-format code
-roc check script.roc   # Type check without running
-roc test script.roc    # Run expect expressions
-```
-
-### Tests with expect
-
-```roc
-add = |a, b| a + b
-
-expect add(2, 3) == 5
-expect add(0, 0) == 0
-```
-
-## Key concepts
-
-- **Immutable**: All values immutable; operations return new values
-- **Type inference**: Types inferred but signatures help clarity
-- **Helpful errors**: Compiler provides detailed, friendly messages
-- **No exceptions**: Use `Result` for errors; no try/catch
-- **No runtime**: Compiled binaries are standalone
-- **Functional**: Functions are first-class; use `|param| expression` syntax
-
-## Maturity caveat
-
-Roc is pre-1.0. Core features work well, but expect:
-- Breaking changes between versions
-- Smaller community/fewer examples
-- Excellent for learning; use production caution

skills/writing-roc-lang/references/builtins-llms.md ๐Ÿ”—

@@ -1,3405 +0,0 @@
-## Full Docs per Module
-### Str
-
-Utf8Problem : [ InvalidStartByte, UnexpectedEndOfSequence, ExpectedContinuation, OverlongEncoding, CodepointTooLarge, EncodesSurrogateHalf ]
-
-is_empty : Str -> Bool
-
-Description:
-Returns [Bool.true] if the string is empty, and [Bool.false] otherwise.
-```roc
-expect Str.is_empty("hi!") == Bool.false
-expect Str.is_empty("") == Bool.true
-```
-
-concat : Str, Str -> Str
-
-Description:
-Concatenates two strings together.
-```roc
-expect Str.concat("ab", "cd") == "abcd"
-expect Str.concat("hello", "") == "hello"
-expect Str.concat("", "") == ""
-```
-
-with_capacity : U64 -> Str
-
-Description:
-Returns an empty string with the specified capacity pre-allocated. Use when building strings incrementally with [Str.concat] to avoid reallocations. Prefer over `""` when concatenating. See [Str.reserve] for existing strings.
-```roc
-Str.with_capacity(45) |> Str.concat("Hello") |> Str.concat(", World!")
-```
-
-reserve : Str, U64 -> Str
-
-Description:
-Increases a string's capacity by at least the given number of additional bytes, preventing reallocations during subsequent [Str.concat] calls. For empty strings, use [Str.with_capacity] instead.
-```roc
-greeting |> Str.reserve(21) |> Str.concat(", ") |> Str.concat(subject) |> Str.concat("!")
-```
-
-join_with : List Str, Str -> Str
-
-Description:
-Combines a [List] of strings into a single string, with a separator
-string in between each.
-```roc
-expect Str.join_with(["one", "two", "three"], ", ") == "one, two, three"
-expect Str.join_with(["1", "2", "3", "4"], ".") == "1.2.3.4"
-```
-
-split_on : Str, Str -> List Str
-
-Description:
-Split a string around a separator.
-
-Passing `""` for the separator is not useful;
-it returns the original string wrapped in a [List].
-```roc
-expect Str.split_on("1,2,3", ",") == ["1","2","3"]
-expect Str.split_on("1,2,3", "") == ["1,2,3"]
-```
-
-repeat : Str, U64 -> Str
-
-Description:
-Repeats a string the given number of times.
-```roc
-expect Str.repeat("z", 3) == "zzz"
-expect Str.repeat("na", 8) == "nananananananana"
-```
-Returns `""` when given `""` for the string or `0` for the count.
-```roc
-expect Str.repeat("", 10) == ""
-expect Str.repeat("anything", 0) == ""
-```
-
-len : Str -> [LearnAboutStringsInRoc Str]
-
-Description:
-A stub function to help people discover [how they should handle this in Roc](https://www.roc-lang.org/faq.html#strings-in-roc).
-
-to_utf8 : Str -> List U8
-
-Description:
-Returns a [List] of the string's [U8] UTF-8 [code units](https://unicode.org/glossary/#code_unit).
-(To split the string into a [List] of smaller [Str] values instead of [U8] values,
-see [Str.split_on].)
-```roc
-expect Str.to_utf8("Roc") == [82, 111, 99]
-expect Str.to_utf8("้น") == [233, 185, 143]
-expect Str.to_utf8("เฎšเฎฟ") == [224, 174, 154, 224, 174, 191]
-expect Str.to_utf8("๐Ÿฆ") == [240, 159, 144, 166]
-```
-
-from_utf8 : List U8 -> Result Str [ BadUtf8 { problem : Utf8Problem, index : U64 } ]
-
-Description:
-Converts a [List] of [U8] UTF-8 [code units](https://unicode.org/glossary/#code_unit) to a string.
-
-Returns `Err` if the given bytes are invalid UTF-8, and returns `Ok ""` when given `[]`.
-```roc
-expect Str.from_utf8([82, 111, 99]) == Ok("Roc")
-expect Str.from_utf8([233, 185, 143]) == Ok("้น")
-expect Str.from_utf8([224, 174, 154, 224, 174, 191]) == Ok("เฎšเฎฟ")
-expect Str.from_utf8([240, 159, 144, 166]) == Ok("๐Ÿฆ")
-expect Str.from_utf8([]) == Ok("")
-expect Str.from_utf8([255]) |> Result.is_err
-```
-
-from_utf8_lossy : List U8 -> Str
-
-Description:
-Converts a [List] of [U8] UTF-8 [code units](https://unicode.org/glossary/#code_unit) to a string.
-Any grouping of invalid byte sequences are replaced with a single unicode replacement character '๏ฟฝ'.
-
-An invalid byte sequence is defined as
-- a 2-byte-sequence starting byte, followed by less than 1 continuation byte
-- a 3-byte-sequence starting byte, followed by less than 2 continuation bytes
-- a 4-byte-sequence starting byte, followed by less than 3 continuation bytes
-- an invalid codepoint from the surrogate pair block
-- an invalid codepoint greater than 0x110000 encoded as a 4-byte sequence
-- any valid codepoint encoded as an incorrect sequence, for instance a codepoint that should be a 2-byte sequence encoded as a 3- or 4-byte sequence
-
-```roc
-expect (Str.from_utf8_lossy [82, 111, 99, 240, 159, 144, 166]) == "Roc๐Ÿฆ"
-expect (Str.from_utf8_lossy [82, 255, 99]) == "R๏ฟฝc"
-expect (Str.from_utf8_lossy [82, 0xED, 0xA0, 0xBD, 99]) == "R๏ฟฝc"
-```
-
-from_utf16 : List U16 -> Result Str [ BadUtf16 { problem : Utf8Problem, index : U64 } ]
-
-Description:
-Converts a [List] of [U16] UTF-16 (little-endian) [code units](https://unicode.org/glossary/#code_unit) to a string.
-
-```roc
-expect Str.from_utf16([82, 111, 99]) == Ok("Roc")
-expect Str.from_utf16([0xb9a, 0xbbf]) == Ok("เฎšเฎฟ")
-expect Str.from_utf16([0xd83d, 0xdc26]) == Ok("๐Ÿฆ")
-expect Str.from_utf16([]) == Ok("")
-# unpaired surrogates, first and second halves
-expect Str.from_utf16([82, 0xd83d, 99]) |> Result.is_err
-expect Str.from_utf16([82, 0xdc96, 99]) |> Result.is_err
-```
-
-from_utf16_lossy : List U16 -> Str
-
-Description:
-Converts a [List] of [U16] UTF-16 (little-endian) [code units](https://unicode.org/glossary/#code_unit) to a string.
-Any unpaired surrogate code unit is replaced with a single unicode replacement character '๏ฟฝ'.
-
-```roc
-expect Str.from_utf16_lossy([82, 111, 99, 0xd83d, 0xdc26]) == "Roc๐Ÿฆ"
-expect Str.from_utf16_lossy([82, 0xdc96, 99]) == "R๏ฟฝc"
-```
-
-from_utf32 : List U32 -> Result Str [ BadUtf32 { problem : Utf8Problem, index : U64 } ]
-
-from_utf32_lossy : List U32 -> Str
-
-Description:
-Converts a [List] of [U32] UTF-32 [code units](https://unicode.org/glossary/#code_unit) to a string.
-Any invalid code points are replaced with a single unicode replacement character '๏ฟฝ'.
-```roc
-expect Str.from_utf32_lossy([82, 111, 99, 0x1f426]) == "Roc๐Ÿฆ"
-expect Str.from_utf32_lossy([82, 0x110000, 99]) == "R๏ฟฝc"
-```
-
-starts_with : Str, Str -> Bool
-
-Description:
-Check if the given [Str] starts with a value.
-```roc
-expect Str.starts_with("ABC", "A") == Bool.true
-expect Str.starts_with("ABC", "X") == Bool.false
-```
-
-ends_with : Str, Str -> Bool
-
-Description:
-Check if the given [Str] ends with a value.
-```roc
-expect Str.ends_with("ABC", "C") == Bool.true
-expect Str.ends_with("ABC", "X") == Bool.false
-```
-
-trim : Str -> Str
-
-Description:
-Return the [Str] with all whitespace removed from both the beginning
-as well as the end.
-```roc
-expect Str.trim("   Hello      \n\n") == "Hello"
-```
-
-trim_start : Str -> Str
-
-Description:
-Return the [Str] with all whitespace removed from the beginning.
-```roc
-expect Str.trim_start("   Hello      \n\n") == "Hello      \n\n"
-```
-
-trim_end : Str -> Str
-
-Description:
-Return the [Str] with all whitespace removed from the end.
-```roc
-expect Str.trim_end("   Hello      \n\n") == "   Hello"
-```
-
-to_dec : Str -> Result Dec [InvalidNumStr]
-
-Description:
-Encode a [Str] to a [Dec]. A [Dec] value is a 128-bit decimal
-[fixed-point number](https://en.wikipedia.org/wiki/Fixed-point_arithmetic).
-```roc
-expect Str.to_dec("10") == Ok(10dec)
-expect Str.to_dec("-0.25") == Ok(-0.25dec)
-expect Str.to_dec("not a number") == Err(InvalidNumStr)
-```
-
-to_f64 : Str -> Result F64 [InvalidNumStr]
-
-Description:
-Encode a [Str] to a [F64]. A [F64] value is a 64-bit
-[floating-point number](https://en.wikipedia.org/wiki/IEEE_754) and can be
-specified with a `f64` suffix.
-```roc
-expect Str.to_f64("0.10") == Ok(0.10f64)
-expect Str.to_f64("not a number") == Err(InvalidNumStr)
-```
-
-to_f32 : Str -> Result F32 [InvalidNumStr]
-
-Description:
-Encode a [Str] to a [F32].A [F32] value is a 32-bit
-[floating-point number](https://en.wikipedia.org/wiki/IEEE_754) and can be
-specified with a `f32` suffix.
-```roc
-expect Str.to_f32("0.10") == Ok(0.10f32)
-expect Str.to_f32("not a number") == Err(InvalidNumStr)
-```
-
-to_u128 : Str -> Result U128 [InvalidNumStr]
-
-Description:
-Encode a [Str] to an unsigned [U128] integer. A [U128] value can hold numbers
-from `0` to `340_282_366_920_938_463_463_374_607_431_768_211_455` (over
-340 undecillion). It can be specified with a u128 suffix.
-```roc
-expect Str.to_u128("1500") == Ok(1500u128)
-expect Str.to_u128("0.1") == Err(InvalidNumStr)
-expect Str.to_u128("-1") == Err(InvalidNumStr)
-expect Str.to_u128("not a number") == Err(InvalidNumStr)
-```
-
-to_i128 : Str -> Result I128 [InvalidNumStr]
-
-Description:
-Encode a [Str] to a signed [I128] integer. A [I128] value can hold numbers
-from `-170_141_183_460_469_231_731_687_303_715_884_105_728` to
-`170_141_183_460_469_231_731_687_303_715_884_105_727`. It can be specified
-with a i128 suffix.
-```roc
-expect Str.to_u128("1500") == Ok(1500i128)
-expect Str.to_i128("-1") == Ok(-1i128)
-expect Str.to_i128("0.1") == Err(InvalidNumStr)
-expect Str.to_i128("not a number") == Err(InvalidNumStr)
-```
-
-to_u64 : Str -> Result U64 [InvalidNumStr]
-
-Description:
-Encode a [Str] to an unsigned [U64] integer. A [U64] value can hold numbers
-from `0` to `18_446_744_073_709_551_615` (over 18 quintillion). It
-can be specified with a u64 suffix.
-```roc
-expect Str.to_u64("1500") == Ok(1500u64)
-expect Str.to_u64("0.1") == Err(InvalidNumStr)
-expect Str.to_u64("-1") == Err(InvalidNumStr)
-expect Str.to_u64("not a number") == Err(InvalidNumStr)
-```
-
-to_i64 : Str -> Result I64 [InvalidNumStr]
-
-Description:
-Encode a [Str] to a signed [I64] integer. A [I64] value can hold numbers
-from `-9_223_372_036_854_775_808` to `9_223_372_036_854_775_807`. It can be
-specified with a i64 suffix.
-```roc
-expect Str.to_i64("1500") == Ok(1500i64)
-expect Str.to_i64("-1") == Ok(-1i64)
-expect Str.to_i64("0.1") == Err(InvalidNumStr)
-expect Str.to_i64("not a number") == Err(InvalidNumStr)
-```
-
-to_u32 : Str -> Result U32 [InvalidNumStr]
-
-Description:
-Encode a [Str] to an unsigned [U32] integer. A [U32] value can hold numbers
-from `0` to `4_294_967_295` (over 4 billion). It can be specified with
-a u32 suffix.
-```roc
-expect Str.to_u32("1500") == Ok(1500u32)
-expect Str.to_u32("0.1") == Err(InvalidNumStr)
-expect Str.to_u32("-1") == Err(InvalidNumStr)
-expect Str.to_u32("not a number") == Err(InvalidNumStr)
-```
-
-to_i32 : Str -> Result I32 [InvalidNumStr]
-
-Description:
-Encode a [Str] to a signed [I32] integer. A [I32] value can hold numbers
-from `-2_147_483_648` to `2_147_483_647`. It can be
-specified with a i32 suffix.
-```roc
-expect Str.to_i32("1500") == Ok(1500i32)
-expect Str.to_i32("-1") == Ok(-1i32)
-expect Str.to_i32("0.1") == Err(InvalidNumStr)
-expect Str.to_i32("not a number") == Err(InvalidNumStr)
-```
-
-to_u16 : Str -> Result U16 [InvalidNumStr]
-
-Description:
-Encode a [Str] to an unsigned [U16] integer. A [U16] value can hold numbers
-from `0` to `65_535`. It can be specified with a u16 suffix.
-```roc
-expect Str.to_u16("1500") == Ok(1500u16)
-expect Str.to_u16("0.1") == Err(InvalidNumStr)
-expect Str.to_u16("-1") == Err(InvalidNumStr)
-expect Str.to_u16("not a number") == Err(InvalidNumStr)
-```
-
-to_i16 : Str -> Result I16 [InvalidNumStr]
-
-Description:
-Encode a [Str] to a signed [I16] integer. A [I16] value can hold numbers
-from `-32_768` to `32_767`. It can be
-specified with a i16 suffix.
-```roc
-expect Str.to_i16("1500") == Ok(1500i16)
-expect Str.to_i16("-1") == Ok(-1i16)
-expect Str.to_i16("0.1") == Err(InvalidNumStr)
-expect Str.to_i16("not a number") == Err(InvalidNumStr)
-```
-
-to_u8 : Str -> Result U8 [InvalidNumStr]
-
-Description:
-Encode a [Str] to an unsigned [U8] integer. A [U8] value can hold numbers
-from `0` to `255`. It can be specified with a u8 suffix.
-```roc
-expect Str.to_u8("250") == Ok(250u8)
-expect Str.to_u8("-0.1") == Err(InvalidNumStr)
-expect Str.to_u8("not a number") == Err(InvalidNumStr)
-expect Str.to_u8("1500") == Err(InvalidNumStr)
-```
-
-to_i8 : Str -> Result I8 [InvalidNumStr]
-
-Description:
-Encode a [Str] to a signed [I8] integer. A [I8] value can hold numbers
-from `-128` to `127`. It can be
-specified with a i8 suffix.
-```roc
-expect Str.to_i8("-15") == Ok(-15i8)
-expect Str.to_i8("150.00") == Err(InvalidNumStr)
-expect Str.to_i8("not a number") == Err(InvalidNumStr)
-```
-
-count_utf8_bytes : Str -> U64
-
-Description:
-Gives the number of bytes in a [Str] value.
-```roc
-expect Str.count_utf8_bytes("Hello World") == 11
-```
-
-replace_each : Str, Str, Str -> Str
-
-Description:
-Returns the given [Str] with each occurrence of a substring replaced.
-If the substring is not found, returns the original string.
-
-```roc
-expect Str.replace_each("foo/bar/baz", "/", "_") == "foo_bar_baz"
-expect Str.replace_each("not here", "/", "_") == "not here"
-```
-
-replace_first : Str, Str, Str -> Str
-
-Description:
-Returns the given [Str] with the first occurrence of a substring replaced.
-If the substring is not found, returns the original string.
-
-```roc
-expect Str.replace_first("foo/bar/baz", "/", "_") == "foo_bar/baz"
-expect Str.replace_first("no slashes here", "/", "_") == "no slashes here"
-```
-
-replace_last : Str, Str, Str -> Str
-
-Description:
-Returns the given [Str] with the last occurrence of a substring replaced.
-If the substring is not found, returns the original string.
-
-```roc
-expect Str.replace_last("foo/bar/baz", "/", "_") == "foo/bar_baz"
-expect Str.replace_last("no slashes here", "/", "_") == "no slashes here"
-```
-
-split_first : Str, Str -> Result { before : Str, after : Str } [NotFound]
-
-Description:
-Returns the given [Str] before the first occurrence of a [delimiter](https://www.computerhope.com/jargon/d/delimite.htm), as well
-as the rest of the string after that occurrence.
-Returns [Err NotFound] if the delimiter is not found.
-```roc
-expect Str.split_first("foo/bar/baz", "/") == Ok({ before: "foo", after: "bar/baz" })
-expect Str.split_first("no slashes here", "/") == Err(NotFound)
-```
-
-split_last : Str, Str -> Result { before : Str, after : Str } [NotFound]
-
-Description:
-Returns the given [Str] before the last occurrence of a delimiter, as well as
-the rest of the string after that occurrence.
-Returns [Err NotFound] if the delimiter is not found.
-```roc
-expect Str.split_last("foo/bar/baz", "/") == Ok({ before: "foo/bar", after: "baz" })
-expect Str.split_last("no slashes here", "/") == Err(NotFound)
-```
-
-walk_utf8_with_index : Str, state, (state, U8, U64 -> state) -> state
-
-Description:
-Walks over the `UTF-8` bytes of the given [Str] and calls a function to update
-state for each byte. The index for that byte in the string is provided
-to the update function.
-```roc
-f : List U8, U8, U64 -> List U8
-f = \state, byte, _ -> List.append(state, byte)
-expect Str.walk_utf8_with_index("ABC", [], f) == [65, 66, 67]
-```
-
-walk_utf8 : Str, state, (state, U8 -> state) -> state
-
-Description:
-Walks over the `UTF-8` bytes of the given [Str] and calls a function to update
-state for each byte.
-
-```roc
-sum_of_utf8_bytes =
-    Str.walk_utf8("Hello, World!", 0, (\total, byte ->
-        total + byte
-    ))
-
-expect sum_of_utf8_bytes == 105
-```
-
-release_excess_capacity : Str -> Str
-
-Description:
-Shrink the memory footprint of a str such that its capacity and length are equal.
-Note: This will also convert seamless slices to regular lists.
-
-with_prefix : Str, Str -> Str
-
-Description:
-Adds a prefix to the given [Str].
-```roc
-expect Str.with_prefix("Awesome", "Roc") == "RocAwesome"
-```
-
-contains : Str, Str -> Bool
-
-Description:
-Determines whether or not the first Str contains the second.
-```roc
-expect Str.contains("foobarbaz", "bar")
-expect !Str.contains("apple", "orange")
-expect Str.contains("anything", "")
-```
-
-drop_prefix : Str, Str -> Str
-
-Description:
-Drops the given prefix [Str] from the start of a [Str]
-If the prefix is not found, returns the original string.
-
-```roc
-expect Str.drop_prefix("bar", "foo") == "bar"
-expect Str.drop_prefix("foobar", "foo") == "bar"
-```
-
-drop_suffix : Str, Str -> Str
-
-Description:
-Drops the given suffix [Str] from the end of a [Str]
-If the suffix is not found, returns the original string.
-
-```roc
-expect Str.drop_suffix("bar", "foo") == "bar"
-expect Str.drop_suffix("barfoo", "foo") == "bar"
-```
-
-with_ascii_lowercased : Str -> Str
-
-Description:
-Lowercases ASCII characters only; non-ASCII left unchanged. For Unicode capitalization, use the `unicode` package. See [Str.caseless_ascii_equals] for case-insensitive comparison.
-```roc
-expect Str.with_ascii_lowercased("CAFร‰") == "cafร‰"
-```
-
-with_ascii_uppercased : Str -> Str
-
-Description:
-Uppercases ASCII characters only; non-ASCII left unchanged. For Unicode capitalization, use the `unicode` package. See [Str.caseless_ascii_equals] for case-insensitive comparison.
-```roc
-expect Str.with_ascii_uppercased("cafรฉ") == "CAFรฉ"
-```
-
-caseless_ascii_equals : Str, Str -> Bool
-
-Description:
-Case-insensitive comparison for ASCII characters only; non-ASCII must match exactly. See [Str.with_ascii_uppercased] and [Str.with_ascii_lowercased] for conversion.
-```roc
-expect Str.caseless_ascii_equals("cafรฉ", "CAFรฉ")
-expect !Str.caseless_ascii_equals("cafรฉ", "CAFร‰")  # รฉ โ‰  ร‰ (non-ASCII)
-```
-
-### Num
-
-`Num a` represents either an [Int] or [Frac]. Aliases: `Int a = Num (Integer a)`, `Frac a = Num (Fraction a)`.
-
-Untyped literals default to [I64] (integers) or [Dec] (decimals). Use suffixes for specific types: `215u8`, `76.4f32`, `123.45dec`.
-
-## Int Types
-
-Signed ([I8]-[I128]) can be negative; unsigned ([U8]-[U128]) cannot. Overflow crashes.
-
-| Type | Bytes | Range |
-|------|-------|-------|
-| I8/U8 | 1 | -128..127 / 0..255 |
-| I16/U16 | 2 | -32768..32767 / 0..65535 |
-| I32/U32 | 4 | ยฑ2.1B / 0..4.3B |
-| I64/U64 | 8 | ยฑ9.2ร—10ยนโธ / 0..1.8ร—10ยนโน |
-| I128/U128 | 16 | ยฑ1.7ร—10ยณโธ / 0..3.4ร—10ยณโธ |
-
-## Frac Types
-
-- [Dec]: 128-bit fixed-point, 18 decimal places. `0.1 + 0.2 == 0.3` (precise). Default for decimals.
-- [F32]/[F64]: Floating-point. Faster but imprecise: `0.1f64 + 0.2 != 0.3`. Has infinity/NaN.
-
-Special float values (IEEE-754): โˆž (pos/0.0), -โˆž (neg/0.0), NaN (0.0/0.0). Check with #is_nan, #is_finite, #is_infinite.
-
-**Performance**: Dec add/sub similar to F64; Dec mul ~15x slower, div ~55x slower, trig ~2-4x slower. Use F64/F32 for performance-critical graphics/trig.
-
-e : Frac *
-
-Description:
-Euler's number (e)
-
-pi : Frac *
-
-Description:
-Archimedes' constant (ฯ€)
-
-tau : Frac *
-
-Description:
-Circle constant (ฯ„)
-
-to_str : Num * -> Str
-
-Description:
-Convert a number to a [Str].
-
-```roc
-Num.to_str(42)
-```
-Only [Frac] values will include a decimal point, and they will always include one.
-```roc
-Num.to_str(4.2)
-Num.to_str(4.0)
-```
-When this function is given a non-[finite](Num#is_finite)
-[F64] or [F32] value, the returned string will be `"NaN"`, `"โˆž"`, or `"-โˆž"`.
-
-
-int_cast : Int a -> Int b
-
-Description:
-Convert an [Int] to a new [Int] of the expected type:
-
-```roc
-# Casts a U8 to a U16
-x : U16
-x = Num.int_cast(255u8)
-```
-
-In the case of downsizing, information is lost:
-
-```roc
-# returns 0, as the bits were truncated.
-x : U8
-x = Num.int_cast(256u16)
-```
-
-
-compare : Num a, Num a -> [ LT, EQ, GT ]
-
-is_lt : Num a, Num a -> Bool
-
-Description:
-Returns `Bool.true` if the first number is less than the second.
-
-`a < b` is shorthand for `Num.is_lt(a, b)`.
-
-If either argument is [*NaN*](Num#is_nan), returns `Bool.false` no matter what. (*NaN*
-is [defined to be unordered](https://en.wikipedia.org/wiki/NaN#Comparison_with_NaN).)
-```roc
-5
-    |> Num.is_lt 6
-```
-
-is_gt : Num a, Num a -> Bool
-
-Description:
-Returns `Bool.true` if the first number is greater than the second.
-
-`a > b` is shorthand for `Num.is_gt a b`.
-
-If either argument is [*NaN*](Num#is_nan), returns `Bool.false` no matter what. (*NaN*
-is [defined to be unordered](https://en.wikipedia.org/wiki/NaN#Comparison_with_NaN).)
-```roc
-Num.is_gt(6, 5)
-```
-
-is_lte : Num a, Num a -> Bool
-
-Description:
-Returns `Bool.true` if the first number is less than or equal to the second.
-
-`a <= b` is shorthand for `Num.is_lte(a, b)`.
-
-If either argument is [*NaN*](Num#is_nan), returns `Bool.false` no matter what. (*NaN*
-is [defined to be unordered](https://en.wikipedia.org/wiki/NaN#Comparison_with_NaN).)
-
-is_gte : Num a, Num a -> Bool
-
-Description:
-Returns `Bool.true` if the first number is greater than or equal to the second.
-
-`a >= b` is shorthand for `Num.is_gte(a, b)`.
-
-If either argument is [*NaN*](Num#is_nan), returns `Bool.false` no matter what. (*NaN*
-is [defined to be unordered](https://en.wikipedia.org/wiki/NaN#Comparison_with_NaN).)
-
-is_approx_eq : Frac a, Frac a, { rtol ? Frac a, atol ? Frac a } -> Bool
-
-Description:
-Returns `Bool.true` if the first number and second number are within a specific threshold
-
-A specific relative and absolute tolerance can be provided to change the threshold
-
-This function is symmetric: `Num.is_approx_eq(a, b) == Num.is_approx_eq(b, a)`
-
-If either argument is [*NaN*](Num#is_nan), returns `Bool.false` no matter what. (*NaN*
-is [defined to be unordered](https://en.wikipedia.org/wiki/NaN#Comparison_with_NaN).)
-
-is_zero : Num a -> Bool
-
-Description:
-Returns `Bool.true` if the number is `0`, and `Bool.false` otherwise.
-
-is_even : Int a -> Bool
-
-Description:
-A number is even if dividing it by 2 gives a remainder of 0.
-
-Examples of even numbers: 0, 2, 4, 6, 8, -2, -4, -6, -8
-
-is_odd : Int a -> Bool
-
-Description:
-A number is odd if dividing it by 2 gives a remainder of 1.
-
-Examples of odd numbers: 1, 3, 5, 7, -1, -3, -5, -7
-
-is_positive : Num a -> Bool
-
-Description:
-Positive numbers are greater than `0`.
-
-is_negative : Num a -> Bool
-
-Description:
-Negative numbers are less than `0`.
-
-to_frac : Num * -> Frac *
-
-is_nan : Frac * -> Bool
-
-Description:
-Returns `Bool.true` if the [Frac] is not a number as defined by [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754)
-
-```roc
-Num.is_nan(0 / 0)
-```
-
-is_infinite : Frac * -> Bool
-
-Description:
-Returns `Bool.true` if the [Frac] is positive or negative infinity as defined by [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754)
-
-```roc
-Num.is_infinite(1 / 0)
-
-Num.is_infinite(-1 / 0)
-```
-
-is_finite : Frac * -> Bool
-
-Description:
-Returns `Bool.true` if the [Frac] is not an infinity as defined by [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754)
-
-```roc
-Num.is_finite(42)
-```
-
-abs : Num a -> Num a
-
-Description:
-Returns the absolute value of the number.
-
-* For a positive number, returns the same number.
-* For a negative number, returns the same number except positive.
-* For zero, returns zero.
-```roc
-Num.abs(4)
-
-Num.abs(-2.5)
-
-Num.abs(0)
-
-Num.abs(0.0)
-```
-This is safe to use with any [Frac], but it can cause overflow when used with certain [Int] values.
-
-For example, calling #Num.abs on the lowest value of a signed integer (such as [Num.min_i64] or [Num.min_i32]) will cause overflow.
-This is because, for any given size of signed integer (32-bit, 64-bit, etc.) its negated lowest value turns out to be 1 higher than
-the highest value it can represent. (For this reason, calling [Num.neg] on the lowest signed value will also cause overflow.)
-
-Calling this on an unsigned integer (like [U32] or [U64]) never does anything.
-
-abs_diff : Num a, Num a -> Num a
-
-Description:
-Returns the absolute difference between two numbers.
-
-```roc
-Num.abs_diff(5, 3)
-
-Num.abs_diff(-3, 5)
-
-Num.abs_diff(3.0, 5.0)
-```
-
-If the answer to this operation can't fit in the return value (e.g. an
-[I8] answer that's higher than 127 or lower than -128), the result is an
-*overflow*. For [F64] and [F32], overflow results in an answer of either
-โˆž or -โˆž. For all other number types, overflow results in a panic.
-
-neg : Num a -> Num a
-
-Description:
-Returns a negative number when given a positive one, and vice versa.
-```roc
-Num.neg(5)
-
-Num.neg(-2.5)
-
-Num.neg(0)
-
-Num.neg(0.0)
-```
-!! Num.neg is not completely implemented for all types in all contexts, see github.com/roc-lang/roc/issues/6959
-You can use `\some_num -> 0 - some_num` as a workaround.
-
-This is safe to use with any [Frac], but it can cause overflow when used with certain [Int] values.
-
-For example, calling #Num.neg on the lowest value of a signed integer (such as [Num.min_i64] or [Num.min_i32]) will cause overflow.
-This is because, for any given size of signed integer (32-bit, 64-bit, etc.) its negated lowest value turns out to be 1 higher than
-the highest value it can represent. (For this reason, calling #Num.abs on the lowest signed value will also cause overflow.)
-
-Additionally, calling #Num.neg on any unsigned integer (such as any [U64] or [U32] value) other than zero will cause overflow.
-
-(It will never crash when given a [Frac], however, because of how floating point numbers represent positive and negative numbers.)
-
-add : Num a, Num a -> Num a
-
-Description:
-Adds two numbers of the same type.
-
-(To add an [Int] and a [Frac], first convert one so that they both have the same type. There are functions in this module that can convert both [Int] to [Frac] and the other way around.)
-
-`a + b` is shorthand for `Num.add(a, b)`.
-```roc
-5 + 7
-
-Num.add(5, 7)
-```
-`Num.add` can be convenient in pipelines.
-```roc
-Frac.pi
-    |> Num.add(1.0)
-```
-If the answer to this operation can't fit in the return value (e.g. an
-[I8] answer that's higher than 127 or lower than -128), the result is an
-*overflow*. For [F64] and [F32], overflow results in an answer of either
-โˆž or -โˆž. For all other number types, overflow results in a panic.
-
-sub : Num a, Num a -> Num a
-
-Description:
-Subtracts two numbers of the same type.
-
-(To subtract an [Int] and a [Frac], first convert one so that they both have the same type. There are functions in this module that can convert both [Int] to [Frac] and the other way around.)
-
-`a - b` is shorthand for `Num.sub(a, b)`.
-```roc
-7 - 5
-
-Num.sub(7, 5)
-```
-`Num.sub` can be convenient in pipelines.
-```roc
-Frac.pi
-    |> Num.sub(2.0)
-```
-If the answer to this operation can't fit in the return value (e.g. an
-[I8] answer that's higher than 127 or lower than -128), the result is an
-*overflow*. For [F64] and [F32], overflow results in an answer of either
-โˆž or -โˆž. For all other number types, overflow results in a panic.
-
-mul : Num a, Num a -> Num a
-
-Description:
-Multiplies two numbers of the same type.
-
-(To multiply an [Int] and a [Frac], first convert one so that they both have the same type. There are functions in this module that can convert both [Int] to [Frac] and the other way around.)
-
-`a * b` is shorthand for `Num.mul(a, b)`.
-```roc
-5 * 7
-
-Num.mul(5, 7)
-```
-
-`Num.mul` can be convenient in pipelines.
-
-```roc
-Frac.pi
-    |> Num.mul(2.0)
-```
-If the answer to this operation can't fit in the return value (e.g. an
-[I8] answer that's higher than 127 or lower than -128), the result is an
-*overflow*. For [F64] and [F32], overflow results in an answer of either
-โˆž or -โˆž. For all other number types, overflow results in a panic.
-
-min : Num a, Num a -> Num a
-
-Description:
-Obtains the smaller between two numbers of the same type.
-
-```roc
-Num.min(100, 0)
-
-Num.min(3.0, -3.0)
-```
-
-max : Num a, Num a -> Num a
-
-Description:
-Obtains the greater between two numbers of the same type.
-
-```roc
-Num.max(100, 0)
-
-Num.max(3.0, -3.0)
-```
-
-sin : Frac a -> Frac a
-
-cos : Frac a -> Frac a
-
-tan : Frac a -> Frac a
-
-asin : Frac a -> Frac a
-
-acos : Frac a -> Frac a
-
-atan : Frac a -> Frac a
-
-sqrt : Frac a -> Frac a
-
-Description:
-Returns an approximation of the absolute value of a [Frac]'s square root.
-
-The square root of a negative number is an irrational number, and [Frac] only
-supports rational numbers. As such, you should make sure never to pass this
-function a negative number! Calling [sqrt] on a negative [Dec] will cause a panic.
-
-Calling [sqrt] on [F32] and [F64] values follows these rules:
-* Passing a negative [F64] or [F32] returns [*NaN*](Num#is_nan).
-* Passing [*NaN*](Num#is_nan) or -โˆž also returns [*NaN*](Num#is_nan).
-* Passing โˆž returns โˆž.
-
-> These rules come from the [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754)
-> floating point standard. Because almost all modern processors are built to
-> this standard, deviating from these rules has a significant performance
-> cost! Since the most common reason to choose [F64] or [F32] over [Dec] is
-> access to hardware-accelerated performance, Roc follows these rules exactly.
-```roc
-Num.sqrt(4.0)
-
-Num.sqrt(1.5)
-
-Num.sqrt(0.0)
-
-Num.sqrt(-4.0f64)
-```
-
-sqrt_checked : Frac a -> Result (Frac a) [SqrtOfNegative]
-
-log : Frac a -> Frac a
-
-Description:
-Natural logarithm
-
-log_checked : Frac a -> Result (Frac a) [LogNeedsPositive]
-
-div : Frac a, Frac a -> Frac a
-
-Description:
-Divides one [Frac] by another.
-
-`a / b` is shorthand for `Num.div(a, b)`.
-
-[Division by zero is undefined in mathematics](https://en.wikipedia.org/wiki/Division_by_zero).
-As such, you should make sure never to pass zero as the denominator to this function!
-Calling [div] on a [Dec] denominator of zero will cause a panic.
-
-Calling [div] on [F32] and [F64] values follows these rules:
-* Dividing a positive [F64] or [F32] by zero returns โˆž.
-* Dividing a negative [F64] or [F32] by zero returns -โˆž.
-* Dividing a zero [F64] or [F32] by zero returns [*NaN*](Num#is_nan).
-
-> These rules come from the [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754)
-> floating point standard. Because almost all modern processors are built to
-> this standard, deviating from these rules has a significant performance
-> cost! Since the most common reason to choose [F64] or [F32] over [Dec] is
-> access to hardware-accelerated performance, Roc follows these rules exactly.
-
-To divide an [Int] and a [Frac], first convert the [Int] to a [Frac] using
-one of the functions in this module like #to_dec.
-```roc
-5.0 / 7.0
-
-Num.div(5, 7)
-```
-`Num.div` can be convenient in pipelines.
-```roc
-Num.pi
-    |> Num.div (2.0)
-```
-
-div_checked : Frac a, Frac a -> Result (Frac a) [DivByZero]
-
-div_ceil : Int a, Int a -> Int a
-
-div_ceil_checked : Int a, Int a -> Result (Int a) [DivByZero]
-
-div_trunc : Int a, Int a -> Int a
-
-Description:
-Divides two integers, truncating the result towards zero.
-
-`a // b` is shorthand for `Num.div_trunc(a, b)`.
-
-Division by zero is undefined in mathematics. As such, you should make
-sure never to pass zero as the denominator to this function! If you do,
-it will crash.
-```roc
-5 // 7
-
-Num.div_trunc(5, 7)
-
-8 // -3
-
-Num.div_trunc(8, -3)
-```
-
-div_trunc_checked : Int a, Int a -> Result (Int a) [DivByZero]
-
-rem : Int a, Int a -> Int a
-
-Description:
-Obtains the remainder (truncating modulo) from the division of two integers.
-
-`a % b` is shorthand for `Num.rem(a, b)`.
-```roc
-5 % 7
-
-Num.rem(5, 7)
-
--8 % -3
-
-Num.rem(-8, -3)
-```
-
-rem_checked : Int a, Int a -> Result (Int a) [DivByZero]
-
-is_multiple_of : Int a, Int a -> Bool
-
-bitwise_and : Int a, Int a -> Int a
-
-Description:
-Does a "bitwise and". Each bit of the output is 1 if the corresponding bit
-of x AND of y is 1, otherwise it's 0.
-
-bitwise_xor : Int a, Int a -> Int a
-
-Description:
-Does a "bitwise exclusive or". Each bit of the output is the same as the
-corresponding bit in x if that bit in y is 0, and it's the complement of
-the bit in x if that bit in y is 1.
-
-bitwise_or : Int a, Int a -> Int a
-
-Description:
-Does a "bitwise or". Each bit of the output is 0 if the corresponding bit
-of x OR of y is 0, otherwise it's 1.
-
-bitwise_not : Int a -> Int a
-
-Description:
-Returns the complement of x - the number you get by switching each 1 for a
-0 and each 0 for a 1. This is the same as -x - 1.
-
-shift_left_by : Int a, U8 -> Int a
-
-Description:
-Bitwise left shift of a number by another
-
-The least significant bits always become 0. This means that shifting left is
-like multiplying by factors of two for unsigned integers.
-```roc
-shift_left_by(0b0000_0011, 2) == 0b0000_1100
-
-0b0000_0101 |> shift_left_by(2) == 0b0001_0100
-```
-In some languages `shift_left_by` is implemented as a binary operator `<<`.
-
-shift_right_by : Int a, U8 -> Int a
-
-Description:
-Bitwise arithmetic shift of a number by another
-
-The most significant bits are copied from the current.
-```roc
-shift_right_by(0b0000_1100, 2) == 0b0000_0011
-
-0b0001_0100 |> shift_right_by(2) == 0b0000_0101
-
-0b1001_0000 |> shift_right_by(2) == 0b1110_0100
-```
-In some languages `shift_right_by` is implemented as a binary operator `>>>`.
-
-shift_right_zf_by : Int a, U8 -> Int a
-
-Description:
-Bitwise logical right shift of a number by another
-
-The most significant bits always become 0. This means that shifting right is
-like dividing by factors of two for unsigned integers.
-```roc
-shift_right_zf_by(0b0010_1000, 2) == 0b0000_1010
-
-0b0010_1000 |> shift_right_zf_by(2) == 0b0000_1010
-
-0b1001_0000 |> shift_right_zf_by(2) == 0b0010_0100
-```
-In some languages `shift_right_zf_by` is implemented as a binary operator `>>`.
-
-round : Frac * -> Int *
-
-Description:
-Round off the given fraction to the nearest integer.
-
-floor : Frac * -> Int *
-
-ceiling : Frac * -> Int *
-
-pow : Frac a, Frac a -> Frac a
-
-Description:
-Raises a [Frac] to the power of another [Frac].
-
-For an [Int] alternative to this function, see [Num.pow_int]
-
-pow_int : Int a, Int a -> Int a
-
-Description:
-Raises an integer to the power of another, by multiplying the integer by
-itself the given number of times.
-
-This process is known as [exponentiation by squaring](https://en.wikipedia.org/wiki/Exponentiation_by_squaring).
-
-For a [Frac] alternative to this function, which supports negative exponents,
-see #Num.pow.
-
-## Warning
-
-It is very easy for this function to produce an answer
-so large it causes an overflow.
-
-count_leading_zero_bits : Int a -> U8
-
-Description:
-Counts the number of most-significant (leading in a big-Endian sense) zeroes in an integer.
-
-```roc
-Num.count_leading_zero_bits(0b0001_1100u8)
-
-3
-
-Num.count_leading_zero_bits(0b0000_0000u8)
-
-8
-```
-
-count_trailing_zero_bits : Int a -> U8
-
-Description:
-Counts the number of least-significant (trailing in a big-Endian sense) zeroes in an integer.
-
-```roc
-Num.count_trailing_zero_bits(0b0001_1100u8)
-
-2
-
-Num.count_trailing_zero_bits(0b0000_0000u8)
-
-8
-```
-
-count_one_bits : Int a -> U8
-
-Description:
-Counts the number of set bits in an integer.
-
-```roc
-Num.count_one_bits(0b0001_1100u8)
-
-3
-
-Num.count_one_bits(0b0000_0000u8)
-
-0
-```
-
-add_wrap : Int range, Int range -> Int range
-
-add_saturated : Num a, Num a -> Num a
-
-Description:
-Adds two numbers, clamping on the maximum representable number rather than
-overflowing.
-
-This is the same as [Num.add] except for the saturating behavior if the
-addition is to overflow.
-For example, if `x : U8` is 200 and `y : U8` is 100, `add_saturated x y` will
-yield 255, the maximum value of a `U8`.
-
-add_checked : Num a, Num a -> Result (Num a) [Overflow]
-
-Description:
-Adds two numbers and checks for overflow.
-
-This is the same as [Num.add] except if the operation overflows, instead of
-panicking or returning โˆž or -โˆž, it will return `Err Overflow`.
-
-sub_wrap : Int range, Int range -> Int range
-
-sub_saturated : Num a, Num a -> Num a
-
-Description:
-Subtracts two numbers, clamping on the minimum representable number rather
-than overflowing.
-
-This is the same as [Num.sub] except for the saturating behavior if the
-subtraction is to overflow.
-For example, if `x : U8` is 10 and `y : U8` is 20, `sub_saturated x y` will
-yield 0, the minimum value of a `U8`.
-
-sub_checked : Num a, Num a -> Result (Num a) [Overflow]
-
-Description:
-Subtracts two numbers and checks for overflow.
-
-This is the same as [Num.sub] except if the operation overflows, instead of
-panicking or returning โˆž or -โˆž, it will return `Err Overflow`.
-
-mul_wrap : Int range, Int range -> Int range
-
-mul_saturated : Num a, Num a -> Num a
-
-Description:
-Multiplies two numbers, clamping on the maximum representable number rather than
-overflowing.
-
-This is the same as [Num.mul] except for the saturating behavior if the
-addition is to overflow.
-
-mul_checked : Num a, Num a -> Result (Num a) [Overflow]
-
-Description:
-Multiplies two numbers and checks for overflow.
-
-This is the same as [Num.mul] except if the operation overflows, instead of
-panicking or returning โˆž or -โˆž, it will return `Err Overflow`.
-
-
-## Integer Type Bounds
-
-| Type | min | max |
-|------|-----|-----|
-| I8 | -128 | 127 |
-| I16 | -32_768 | 32_767 |
-| I32 | -2_147_483_648 | 2_147_483_647 |
-| I64 | -9_223_372_036_854_775_808 | 9_223_372_036_854_775_807 |
-| I128 | -170_141_183_460_469_231_731_687_303_715_884_105_728 | 170_141_183_460_469_231_731_687_303_715_884_105_727 |
-| U8 | 0 | 255 |
-| U16 | 0 | 65_535 |
-| U32 | 0 | 4_294_967_295 |
-| U64 | 0 | 18_446_744_073_709_551_615 |
-| U128 | 0 | 340_282_366_920_938_463_463_374_607_431_768_211_455 |
-
-Functions: `min_i8`, `max_i8`, `min_u8`, `max_u8`, etc. for all integer types.
-Also: `min_f32`, `max_f32`, `min_f64`, `max_f64` for float bounds.
-
-**Note**: For signed types, `|Num.abs(min_iN)|` > `max_iN`, so `Num.abs(min_iN)` will overflow.
-
-to_i8 : Int * -> I8
-
-Description:
-Converts an [Int] to an [I8]. If the given number can't be precisely represented in an [I8],
-the returned number may be different from the given number.
-
-to_i16 : Int * -> I16
-
-to_i32 : Int * -> I32
-
-to_i64 : Int * -> I64
-
-to_i128 : Int * -> I128
-
-to_u8 : Int * -> U8
-
-to_u16 : Int * -> U16
-
-to_u32 : Int * -> U32
-
-to_u64 : Int * -> U64
-
-to_u128 : Int * -> U128
-
-to_f32 : Num * -> F32
-
-Description:
-Converts a [Num] to an [F32]. If the given number can't be precisely represented in an [F32],
-the returned number may be different from the given number.
-
-to_f64 : Num * -> F64
-
-Description:
-Converts a [Num] to an [F64]. If the given number can't be precisely represented in an [F64],
-the returned number may be different from the given number.
-
-to_i8_checked : Int * -> Result I8 [OutOfBounds]
-
-Description:
-Converts a [Int] to an [I8].
-If the given integer can't be precisely represented in an [I8], returns
-`Err OutOfBounds`.
-
-to_i16_checked : Int * -> Result I16 [OutOfBounds]
-
-to_i32_checked : Int * -> Result I32 [OutOfBounds]
-
-to_i64_checked : Int * -> Result I64 [OutOfBounds]
-
-to_i128_checked : Int * -> Result I128 [OutOfBounds]
-
-to_u8_checked : Int * -> Result U8 [OutOfBounds]
-
-to_u16_checked : Int * -> Result U16 [OutOfBounds]
-
-to_u32_checked : Int * -> Result U32 [OutOfBounds]
-
-to_u64_checked : Int * -> Result U64 [OutOfBounds]
-
-to_u128_checked : Int * -> Result U128 [OutOfBounds]
-
-to_f32_checked : Num * -> Result F32 [OutOfBounds]
-
-to_f64_checked : Num * -> Result F64 [OutOfBounds]
-
-without_decimal_point : Dec -> I128
-
-Description:
-Turns a [Dec] into its [I128] representation by removing the decimal point.
-This is equivalent to multiplying the [Dec] by 10^18.
-
-with_decimal_point : I128 -> Dec
-
-Description:
-Turns a [I128] into the coresponding [Dec] by adding the decimal point.
-This is equivalent to dividing the [I128] by 10^18.
-
-f32_to_parts : F32 -> { sign : Bool, exponent : U8, fraction : U32 }
-
-Description:
-Splits a [F32] into its components according to IEEE 754 standard.
-
-This function is deprecated due to common pitfalls when working with float components
-using Rocโ€™s fixed-size integer types. Please use [Num.f32_to_bits] instead and extract the
-[IEEE 754 parts](https://en.wikipedia.org/wiki/Single-precision_floating-point_format#IEEE_754_standard:_binary32)
-manually from the resulting [U32].
-
-f64_to_parts : F64 -> { sign : Bool, exponent : U16, fraction : U64 }
-
-Description:
-Splits a [F64] into its components according to IEEE 754 standard.
-
-This function is deprecated due to common pitfalls when working with float components
-using Rocโ€™s fixed-size integer types. Please use [Num.f64_to_bits] instead and extract the
-[IEEE 754 parts](https://en.wikipedia.org/wiki/Double-precision_floating-point_format#IEEE_754_double-precision_binary_floating-point_format:_binary64)
-manually from the resulting [U64].
-
-f32_from_parts : { sign : Bool, exponent : U8, fraction : U32 } -> F32
-
-Description:
-Combine parts of a [F32] according to IEEE 754 standard.
-The fraction should not be bigger than 0x007F_FFFF, any bigger value will be truncated.
-
-This function is deprecated due to common pitfalls when working with float components
-using Rocโ€™s fixed-size integer types. Please combine the
-[IEEE 754 parts](https://en.wikipedia.org/wiki/Single-precision_floating-point_format#IEEE_754_standard:_binary32)
-manually into a [U32] and use [Num.f32_from_bits] to create the [F32] instead.
-
-f64_from_parts : { sign : Bool, exponent : U16, fraction : U64 } -> F64
-
-Description:
-Combine parts of a [F64] according to IEEE 754 standard.
-The fraction should not be bigger than 0x000F_FFFF_FFFF_FFFF, any bigger value will be truncated.
-The exponent should not be bigger than 0x07FF, any bigger value will be truncated.
-
-This function is deprecated due to common pitfalls when working with float components
-using Rocโ€™s fixed-size integer types. Please combine the
-[IEEE 754 parts](https://en.wikipedia.org/wiki/Double-precision_floating-point_format#IEEE_754_double-precision_binary_floating-point_format:_binary64)
-manually into a [U64] and use [Num.f64_from_bits] to create the [F64] instead.
-
-f32_to_bits : F32 -> U32
-
-Description:
-Returns a [U32] containing the raw bits of a [F32], as defined by the IEEE 754 standard.
-
-f64_to_bits : F64 -> U64
-
-Description:
-Returns a [U64] containing the raw bits of a [F64], as defined by the IEEE 754 standard.
-
-dec_to_bits : Dec -> U128
-
-Description:
-Returns a [U128] containing the raw bits of a [Dec], which corresponds to the raw bits
-of its [I128] representation.
-
-f32_from_bits : U32 -> F32
-
-Description:
-Interprets a [U32] as the binary representation of a 32-bit floating-point value according
-to the IEEE 754 standard and returns the corresponding [F32].
-
-f64_from_bits : U64 -> F64
-
-Description:
-Interprets a [U64] as the binary representation of a 64-bit floating-point value according
-to the IEEE 754 standard and returns the corresponding [F64].
-
-dec_from_bits : U128 -> Dec
-
-Description:
-Interprets a [U128] as the raw bits of the internal [I128] representation of a fixed-point
-decimal value and returns the corresponding [Dec].
-
-from_bool : Bool -> Num *
-
-Description:
-Convert a `Bool` to a `Num`
-```roc
-expect Num.from_bool(Bool.true) == 1
-expect Num.from_bool(Bool.false) == 0
-```
-
-nan_f32 : F32
-
-Description:
-The value for not-a-number for a [F32] according to the IEEE 754 standard.
-
-nan_f64 : F64
-
-Description:
-The value for not-a-number for a [F64] according to the IEEE 754 standard.
-
-infinity_f32 : F32
-
-Description:
-The value for infinity for a [F32] according to the IEEE 754 standard.
-
-infinity_f64 : F64
-
-Description:
-The value for infinity for a [F64] according to the IEEE 754 standard.
-
-### Bool
-
-Eq : implements
-    is_eq : a, a -> Bool
-        where a implements Eq
-
-Description:
-Defines a type that can be compared for total equality.
-
-Total equality means that all values of the type can be compared to each
-other, and two values `a`, `b` are identical if and only if `is_eq(a, b)` is
-`Bool.true`.
-
-Not all types support total equality. For example, [`F32`](Num#F32) and [`F64`](Num#F64) can
-be a `NaN` ([Not a Number](https://en.wikipedia.org/wiki/NaN)), and the
-[IEEE-754](https://en.wikipedia.org/wiki/IEEE_754) floating point standard
-specifies that two `NaN`s are not equal.
-
-Description:
-Represents the boolean true and false using an opaque type.
-`Bool` implements the `Eq` ability.
-
-true : Bool
-
-Description:
-The boolean true value.
-
-false : Bool
-
-Description:
-The boolean false value.
-
-not : Bool -> Bool
-
-Description:
-Returns `Bool.false` when given `Bool.true`, and vice versa. This is
-equivalent to the logic [NOT](https://en.wikipedia.org/wiki/Negation)
-gate. The operator `!` can also be used as shorthand for `Bool.not`.
-```roc
-expect Bool.not(Bool.false) == Bool.true
-expect !Bool.false == Bool.true
-```
-
-is_not_eq : a, a -> Bool where a implements Eq
-
-Description:
-This will call the function `Bool.is_eq` on the inputs, and then `Bool.not`
-on the result. The is equivalent to the logic
-[XOR](https://en.wikipedia.org/wiki/Exclusive_or) gate. The infix operator
-`!=` can also be used as shorthand for `Bool.is_not_eq`.
-
-**Note** that `is_not_eq` does not accept arguments whose types contain
-functions.
-```roc
-expect Bool.is_not_eq(Bool.false, Bool.true) == Bool.true
-expect (Bool.false != Bool.false) == Bool.false
-expect "Apples" != "Oranges"
-```
-
-### Result
-
-Result : [ Ok ok, Err err ]
-
-Description:
-The result of an operation that could fail: either the operation went
-okay, or else there was an error of some sort.
-
-is_ok : Result ok err -> Bool
-
-Description:
-Returns `Bool.true` if the result indicates a success, else returns `Bool.false`.
-```roc
-Result.is_ok(Ok(5))
-```
-
-is_err : Result ok err -> Bool
-
-Description:
-Returns `Bool.true` if the result indicates a failure, else returns `Bool.false`.
-```roc
-Result.is_err(Err("uh oh"))
-```
-
-with_default : Result ok err, ok -> ok
-
-Description:
-If the result is `Ok`, returns the value it holds. Otherwise, returns
-the given default value.
-
-Note: This function should be used sparingly, because it hides that an error
-happened, which will make debugging harder. Prefer using `?` to forward errors or
-handle them explicitly with `when`.
-```roc
-Result.with_default(Err("uh oh"), 42) # = 42
-
-Result.with_default(Ok(7), 42) # = 7
-```
-
-map_ok : Result a err, (a -> b) -> Result b err
-
-Description:
-If the result is `Ok`, transforms the value it holds by running a conversion
-function on it. Then returns a new `Ok` holding the transformed value. If the
-result is `Err`, this has no effect. Use [map_err] to transform an `Err`.
-```roc
-Result.map_ok(Ok(12), Num.neg) # = Ok(-12)
-
-Result.map_ok(Err("yipes!"), Num.neg) # = Err("yipes!")
-```
-Functions like `map` are common in Roc; see for example [List.map],
-`Set.map`, and `Dict.map`.
-
-map_err : Result ok a, (a -> b) -> Result ok b
-
-Description:
-If the result is `Err`, transforms the value it holds by running a conversion
-function on it. Then returns a new `Err` holding the transformed value. If
-the result is `Ok`, this has no effect. Use [map_ok] to transform an `Ok`.
-```roc
-List.last([]) |> Result.map_err(|_| ProvidedListIsEmpty) # = Err(ProvidedListIsEmpty)
-
-List.last([4]) |> Result.map_err(|_| ProvidedListIsEmpty) # = Ok(4)
-```
-
-on_err : Result a err, (err -> Result a other_err) -> Result a other_err
-
-Description:
-If the result is `Err`, transforms the entire result by running a conversion
-function on the value the `Err` holds. Then returns that new result. If the
-result is `Ok`, this has no effect. Use `?` or [try] to transform an `Ok`.
-```roc
-Result.on_err(Ok(10), Str.to_u64) # = Ok(10)
-
-Result.on_err(Err("42"), Str.to_u64) # = Ok(42)
-
-Result.on_err(Err("string"), Str.to_u64) # = Err(InvalidNumStr)
-```
-
-on_err! : Result a err, (err => Result a other_err) => Result a other_err
-
-Description:
-Like [on_err], but it allows the transformation function to produce effects.
-
-```roc
-Result.on_err(
-    Err("missing user"),
-    |msg|
-        Stdout.line!("ERROR: ${msg}")?
-        Err(msg)
-)
-```
-
-map_both : Result ok1 err1, (ok1 -> ok2), (err1 -> err2) -> Result ok2 err2
-
-Description:
-Maps both the `Ok` and `Err` values of a `Result` to new values.
-
-map2 : Result a err, Result b err, (a, b -> c) -> Result c err
-
-Description:
-Maps the `Ok` values of two `Result`s to a new value using a given transformation,
-or returns the first `Err` value encountered.
-
-try : Result a err, (a -> Result b err) -> Result b err
-
-Description:
-If the result is `Ok`, transforms the entire result by running a conversion
-function on the value the `Ok` holds. Then returns that new result. If the
-result is `Err`, this has no effect.
-
-We recommend using `?` instead of `try`, it makes the code easier to read.
-```roc
-Result.try(Ok(-1), (|num| if num < 0 then Err("negative!") else Ok(-num))) # = Err("negative!")
-
-Result.try(Err("yipes!"), (|num| -> if num < 0 then Err("negative!") else Ok(-num))) # = Err("yipes!")
-```
-
-### List
-
-is_empty : List * -> Bool
-
-Description:
- Check if the list is empty.
-```roc
-List.is_empty([1, 2, 3])
-
-List.is_empty([])
-```
-
-get : List a, U64 -> Result a [OutOfBounds]
-
-Description:
-Returns an element from a list at the given index.
-
-Returns `Err OutOfBounds` if the given index exceeds the List's length
-```roc
-expect List.get([100, 200, 300], 1) == Ok(200)
-expect List.get([100, 200, 300], 5) == Err(OutOfBounds)
-```
-
-replace : List a, U64, a -> { list : List a, value : a }
-
-set : List a, U64, a -> List a
-
-Description:
-Replaces the element at the given index with a replacement.
-```roc
-List.set(["a", "b", "c"], 1, "B")
-```
-If the given index is outside the bounds of the list, returns the original
-list unmodified.
-
-To drop the element at a given index, instead of replacing it, see [List.drop_at].
-
-update : List a, U64, (a -> a) -> List a
-
-Description:
-Updates the element at the given index with the given function.
-```roc
-List.update([1, 2, 3], 1, (|x| x + 1))
-```
-If the given index is outside the bounds of the list, returns the original
-list unmodified.
-
-To replace the element at a given index, instead of updating based on the current value,
-see [List.set] and [List.replace]
-
-append : List a, a -> List a
-
-Description:
-Add a single element to the end of a list.
-```roc
-List.append([1, 2, 3], 4)
-
-[0, 1, 2]
-    |> List.append(3)
-```
-
-append_if_ok : List a, Result a * -> List a
-
-Description:
-If the given [Result] is `Ok`, add it to the end of a list.
-Otherwise, return the list unmodified.
-
-```roc
-List.append_if_ok([1, 2, 3], Ok(4))
-
-[0, 1, 2]
-    |> List.append_if_ok(Err(3))
-```
-
-prepend : List a, a -> List a
-
-Description:
-Add a single element to the beginning of a list.
-```roc
-List.prepend([1, 2, 3], 0)
-
-[2, 3, 4]
-    |> List.prepend(1)
-```
-
-prepend_if_ok : List a, Result a * -> List a
-
-Description:
-If the given [Result] is `Ok`, add it to the beginning of a list.
-Otherwise, return the list unmodified.
-
-```roc
-List.prepend([1, 2, 3], Ok(0))
-
-[2, 3, 4]
-    |> List.prepend(Err(1))
-```
-
-len : List * -> U64
-
-Description:
-Returns the length of the list - the number of elements it contains.
-
-One [List] can store up to `Num.max_i64` elements on 64-bit targets and `Num.max_i32` on 32-bit targets like wasm.
-This means the #U64 this function returns can always be safely converted to #I64 or #I32, depending on the target.
-
-with_capacity : U64 -> List *
-
-Description:
-Create a list with space for at least capacity elements
-
-reserve : List a, U64 -> List a
-
-Description:
-Enlarge the list for at least capacity additional elements
-
-release_excess_capacity : List a -> List a
-
-Description:
-Shrink the memory footprint of a list such that it's capacity and length are equal.
-Note: This will also convert seamless slices to regular lists.
-
-concat : List a, List a -> List a
-
-Description:
-Put two lists together.
-```roc
-List.concat([1, 2, 3], [4, 5])
-
-[0, 1, 2]
-    |> List.concat([3, 4])
-```
-
-last : List a -> Result a [ListWasEmpty]
-
-Description:
-Returns the last element in the list, or `ListWasEmpty` if it was empty.
-```roc
-expect List.last([1, 2, 3]) == Ok(3)
-expect List.last([]) == Err(ListWasEmpty)
-```
-
-single : a -> List a
-
-Description:
-A list with a single element in it.
-
-This is useful in pipelines, like so:
-```roc
-websites =
-    Str.concat(domain, ".com")
-        |> List.single
-```
-
-repeat : a, U64 -> List a
-
-Description:
-Returns a list with the given length, where every element is the given value.
-
-reverse : List a -> List a
-
-Description:
-Returns the list with its elements reversed.
-```roc
-expect List.reverse([1, 2, 3]) == [3, 2, 1]
-```
-
-join : List (List a) -> List a
-
-Description:
-Join the given lists together into one list.
-```roc
-expect List.join([[1], [2, 3], [], [4, 5]]) == [1, 2, 3, 4, 5]
-expect List.join([[], []]) == []
-expect List.join([]) == []
-```
-
-contains : List a, a -> Bool where a implements Eq
-
-walk : List elem, state, (state, elem -> state) -> state
-
-Description:
-Build a value by folding over list elements from first to last. Also known as `reduce`, `fold`, `foldl`.
-```roc
-[2, 4, 8] |> List.walk(0, Num.add)  # returns 14
-```
-
-walk_with_index : List elem, state, (state, elem, U64 -> state) -> state
-
-Description:
-Like [walk], but at each step the function also receives the index of the current element.
-
-walk_with_index_until : List elem, state, (state, elem, U64 -> [ Continue state, Break state ]) -> state
-
-Description:
-Like [walk_until], but at each step the function also receives the index of the current element.
-
-walk_backwards : List elem, state, (state, elem -> state) -> state
-
-Description:
-Note that in other languages, `walk_backwards` is sometimes called `reduce_right`,
-`fold`, `fold_right`, or `foldr`.
-
-walk_until : List elem, state, (state, elem -> [ Continue state, Break state ]) -> state
-
-Description:
-Like [List.walk], but can stop early by returning `Break state`.
-
-walk_backwards_until : List elem, state, (state, elem -> [ Continue state, Break state ]) -> state
-
-Description:
-Same as [List.walk_until], but does it from the end of the list instead.
-
-walk_from : List elem, U64, state, (state, elem -> state) -> state
-
-Description:
-Walks to the end of the list from a specified starting index
-
-walk_from_until : List elem, U64, state, (state, elem -> [ Continue state, Break state ]) -> state
-
-Description:
-A combination of [List.walk_from] and [List.walk_until]
-
-sum : List (Num a) -> Num a
-
-product : List (Num a) -> Num a
-
-any : List a, (a -> Bool) -> Bool
-
-Description:
-Run the given predicate on each element of the list, returning `Bool.true` if
-any of the elements satisfy it.
-
-all : List a, (a -> Bool) -> Bool
-
-Description:
-Run the given predicate on each element of the list, returning `Bool.true` if
-all of the elements satisfy it.
-
-keep_if : List a, (a -> Bool) -> List a
-
-Description:
-Returns elements where the predicate returns `Bool.true`. Mutates in place if list is unique.
-```roc
-List.keep_if([1, 2, 3, 4], (|num| num > 2))  # [3, 4]
-```
-
-
-keep_if_try! : List a, (a => Result Bool err) => Result (List a) err
-
-Description:
-Run an effectful function that returns a [Result] on each element of a list, and return all the
-elements for which the function returned `Ok(Bool.true)`.
-```roc
-dirs_only = List.keep_if_try!(path_list, Path.is_dir!)?
-```
-
-
-drop_if : List a, (a -> Bool) -> List a
-
-Description:
-Run the given function on each element of a list, and return all the
-elements for which the function returned `Bool.false`.
-```roc
-List.drop_if([1, 2, 3, 4], (|num| num > 2))
-```
-## Performance Details
-
-`List.drop_if` has the same performance characteristics as [List.keep_if].
-See its documentation for details on those characteristics!
-
-count_if : List a, (a -> Bool) -> U64
-
-Description:
-Run the given function on each element of a list, and return the
-number of elements for which the function returned `Bool.true`.
-```roc
-expect List.count_if([1, -2, -3], Num.is_negative) == 2
-expect List.count_if([1, 2, 3], (|num| num > 1)) == 2
-```
-
-keep_oks : List before, (before -> Result after *) -> List after
-
-Description:
-This works like [List.map], except only the transformed values that are
-wrapped in `Ok` are kept. Any that are wrapped in `Err` are dropped.
-```roc
-expect List.keep_oks(["1", "Two", "23", "Bird"], Str.to_i32) == [1, 23]
-
-expect List.keep_oks([["a", "b"], [], ["c", "d", "e"], [] ], List.first) == ["a", "c"]
-
-fn = |str| if Str.is_empty(str) then Err(StrWasEmpty) else Ok(str)
-expect List.keep_oks(["", "a", "bc", "", "d", "ef", ""], fn) == ["a", "bc", "d", "ef"]
-```
-
-keep_errs : List before, (before -> Result * after) -> List after
-
-Description:
-This works like [List.map], except only the transformed values that are
-wrapped in `Err` are kept. Any that are wrapped in `Ok` are dropped.
-```roc
-List.keep_errs([["a", "b"], [], [], ["c", "d", "e"]], List.last)
-
-fn = |str| if Str.is_empty(str) then Err(StrWasEmpty) else Okd(Str.len(str))
-
-List.keep_errs(["", "a", "bc", "", "d", "ef", ""], fn)
-```
-
-map : List a, (a -> b) -> List b
-
-Description:
-Convert each element in the list to something new, by calling a conversion
-function on each of them. Then return a new list of the converted values.
-```roc
-expect List.map([1, 2, 3], (|num| num + 1)) == [2, 3, 4]
-
-expect List.map(["", "a", "bc"], Str.is_empty) == [Bool.true, Bool.false, Bool.false]
-```
-
-map2 : List a, List b, (a, b -> c) -> List c
-
-Description:
-Run a transformation function on the first element of each list,
-and use that as the first element in the returned list.
-Repeat until a list runs out of elements.
-
-Some languages have a function named `zip`, which does something similar to
-calling [List.map2] passing two lists and `Pair`:
-```roc
-zipped = List.map2(["a", "b", "c"], [1, 2, 3], Pair)
-```
-
-map3 : List a, List b, List c, (a, b, c -> d) -> List d
-
-Description:
-Run a transformation function on the first element of each list,
-and use that as the first element in the returned list.
-Repeat until a list runs out of elements.
-
-map4 : List a, List b, List c, List d, (a, b, c, d -> e) -> List e
-
-Description:
-Run a transformation function on the first element of each list,
-and use that as the first element in the returned list.
-Repeat until a list runs out of elements.
-
-map_with_index : List a, (a, U64 -> b) -> List b
-
-Description:
-This works like [List.map], except it also passes the index
-of the element to the conversion function.
-```roc
-expect List.map_with_index([10, 20, 30], (|num, index| num + index)) == [10, 21, 32]
-```
-
-Description:
-Returns a list of all the integers between `start` and `end`.
-
-To include the `start` and `end` integers themselves, use `At` like so:
-```roc
-List.range({ start: At 2, end: At 5 }) == [2, 3, 4, 5]
-```
-To exclude them, use `After` and `Before`, like so:
-```roc
-List.range({ start: After 2, end: Before 5 }) == [3, 4]
-```
-You can have the list end at a certain length rather than a certain integer:
-```roc
-List.range({ start: At 6, end: Length 4 }) == [6, 7, 8, 9]
-```
-If `step` is specified, each integer increases by that much. (`step: 1` is the default.)
-```roc
-List.range({ start: After 0, end: Before 9, step: 3 }) == [3, 6]
-```
-List.range will also generate a reversed list if step is negative or end comes before start:
-```roc
-List.range({ start: At 5, end: At 2 }) == [5, 4, 3, 2]
-```
-All of these options are compatible with the others. For example, you can use `At` or `After`
-with `start` regardless of what `end` and `step` are set to.
-
-sort_with : List a, (a, a -> [ LT, EQ, GT ]) -> List a
-
-Description:
-Sort with a custom comparison function
-
-sort_asc : List (Num a) -> List (Num a)
-
-Description:
-Sorts a list of numbers in ascending order (lowest to highest).
-
-To sort in descending order (highest to lowest), use [List.sort_desc] instead.
-
-sort_desc : List (Num a) -> List (Num a)
-
-Description:
-Sorts a list of numbers in descending order (highest to lowest).
-
-To sort in ascending order (lowest to highest), use [List.sort_asc] instead.
-
-swap : List a, U64, U64 -> List a
-
-first : List a -> Result a [ListWasEmpty]
-
-Description:
-Returns the first element in the list, or `ListWasEmpty` if it was empty.
-
-take_first : List elem, U64 -> List elem
-
-Description:
-Returns the given number of elements from the beginning of the list.
-```roc
-List.take_first([1, 2, 3, 4, 5, 6, 7, 8], 4) == [1, 2, 3, 4]
-```
-If there are fewer elements in the list than the requested number,
-returns the entire list.
-```roc
-List.take_first([1, 2], 5) == [1, 2]
-```
-To *remove* elements from the beginning of the list, use `List.take_last`.
-
-To remove elements from both the beginning and end of the list,
-use `List.sublist`.
-
-To split the list into two lists, use `List.split_at`.
-
-
-take_last : List elem, U64 -> List elem
-
-Description:
-Returns the given number of elements from the end of the list.
-```roc
-List.take_last([1, 2, 3, 4, 5, 6, 7, 8], 4) == [5, 6, 7, 8]
-```
-If there are fewer elements in the list than the requested number,
-returns the entire list.
-```roc
-List.take_last([1, 2], 5) == [1, 2]
-```
-To *remove* elements from the end of the list, use `List.take_first`.
-
-To remove elements from both the beginning and end of the list,
-use `List.sublist`.
-
-To split the list into two lists, use `List.split_at`.
-
-
-drop_first : List elem, U64 -> List elem
-
-Description:
-Drops n elements from the beginning of the list.
-
-drop_last : List elem, U64 -> List elem
-
-Description:
-Drops n elements from the end of the list.
-
-drop_at : List elem, U64 -> List elem
-
-Description:
-Drops the element at the given index from the list.
-
-This has no effect if the given index is outside the bounds of the list.
-
-To replace the element at a given index, instead of dropping it, see [List.set].
-
-min : List (Num a) -> Result (Num a) [ListWasEmpty]
-
-max : List (Num a) -> Result (Num a) [ListWasEmpty]
-
-join_map : List a, (a -> List b) -> List b
-
-Description:
-Like [List.map], except the transformation function wraps the return value
-in a list. At the end, all the lists get joined together into one list.
-
-You may know a similar function named `concat_map` in other languages.
-
-find_first : List elem, (elem -> Bool) -> Result elem [NotFound]
-
-Description:
-Returns the first element of the list satisfying a predicate function.
-If no satisfying element is found, an `Err NotFound` is returned.
-
-find_last : List elem, (elem -> Bool) -> Result elem [NotFound]
-
-Description:
-Returns the last element of the list satisfying a predicate function.
-If no satisfying element is found, an `Err NotFound` is returned.
-
-find_first_index : List elem, (elem -> Bool) -> Result U64 [NotFound]
-
-Description:
-Returns the index at which the first element in the list
-satisfying a predicate function can be found.
-If no satisfying element is found, an `Err NotFound` is returned.
-
-find_last_index : List elem, (elem -> Bool) -> Result U64 [NotFound]
-
-Description:
-Returns the last index at which the first element in the list
-satisfying a predicate function can be found.
-If no satisfying element is found, an `Err NotFound` is returned.
-
-sublist : List elem, { start : U64, len : U64 } -> List elem
-
-Description:
-Returns a subsection of the given list, beginning at the `start` index and
-including a total of `len` elements.
-
-If `start` is outside the bounds of the given list, returns the empty list.
-```roc
-List.sublist([1, 2, 3], { start: 4, len: 0 })
-```
-If more elements are requested than exist in the list, returns as many as it can.
-```roc
-List.sublist([1, 2, 3, 4, 5], { start: 2, len: 10 })
-```
-> If you want a sublist which goes all the way to the end of the list, no
-> matter how long the list is, `List.take_last` can do that more efficiently.
-
-Some languages have a function called **`slice`** which works similarly to this.
-
-intersperse : List elem, elem -> List elem
-
-Description:
-Intersperses `sep` between the elements of `list`
-```roc
-List.intersperse([1, 2, 3], 9) == [1, 9, 2, 9, 3]
-```
-
-starts_with : List elem, List elem -> Bool where elem implements Eq
-
-Description:
-Returns `Bool.true` if the first list starts with the second list.
-
-If the second list is empty, this always returns `Bool.true`; every list
-is considered to "start with" an empty list.
-
-If the first list is empty, this only returns `Bool.true` if the second list is empty.
-
-ends_with : List elem, List elem -> Bool where elem implements Eq
-
-Description:
-Returns `Bool.true` if the first list ends with the second list.
-
-If the second list is empty, this always returns `Bool.true`; every list
-is considered to "end with" an empty list.
-
-If the first list is empty, this only returns `Bool.true` if the second list is empty.
-
-split_at : List elem, U64 -> { before : List elem, others : List elem }
-
-Description:
-Splits the list into two lists, around the given index.
-
-The returned lists are labeled `before` and `others`. The `before` list will
-contain all the elements whose index in the original list was **less than**
-than the given index, # and the `others` list will be all the others. (This
-means if you give an index of 0, the `before` list will be empty and the
-`others` list will have the same elements as the original list.)
-
-split_on : List a, a -> List (List a) where a implements Eq
-
-Description:
-Splits the input list on the delimiter element.
-
-```roc
-List.split_on([1, 2, 3], 2) == [[1], [3]]
-```
-
-split_on_list : List a, List a -> List (List a) where a implements Eq
-
-Description:
-Splits the input list on the delimiter list.
-
-```roc
-List.split_on_list([1, 2, 3], [1, 2]) == [[], [3]]
-```
-
-split_first : List elem, elem -> Result { before : List elem, after : List elem } [NotFound] where elem implements Eq
-
-Description:
-Returns the elements before the first occurrence of a delimiter, as well as the
-remaining elements after that occurrence. If the delimiter is not found, returns `Err`.
-```roc
-List.split_first([Foo, Z, Bar, Z, Baz], Z) == Ok({ before: [Foo], after: [Bar, Z, Baz] })
-```
-
-split_last : List elem, elem -> Result { before : List elem, after : List elem } [NotFound] where elem implements Eq
-
-Description:
-Returns the elements before the last occurrence of a delimiter, as well as the
-remaining elements after that occurrence. If the delimiter is not found, returns `Err`.
-```roc
-List.split_last([Foo, Z, Bar, Z, Baz], Z) == Ok({ before: [Foo, Z, Bar], after: [Baz] })
-```
-
-chunks_of : List a, U64 -> List (List a)
-
-Description:
-Splits the list into many chunks, each of which is length of the given chunk
-size. The last chunk will be shorter if the list does not evenly divide by the
-chunk size. If the provided list is empty or if the chunk size is 0 then the
-result is an empty list.
-
-map_try : List elem, (elem -> Result ok err) -> Result (List ok) err
-
-Description:
-Like [List.map], except the transformation function returns a [Result].
-If that function ever returns `Err`, [map_try] immediately returns that `Err`.
-If it returns `Ok` for every element, [map_try] returns `Ok` with the transformed list.
-
-map_try! : List elem, (elem => Result ok err) => Result (List ok) err
-
-Description:
-Like [List.map_try], but with an effectful function.
-```
-file_list = ["a.txt", "b.txt", "c.txt"]
-file_contents =
-    List.map_try!(file_list, |file| File.read_utf8!(file))
-```
-
-walk_try : List elem, state, (state, elem -> Result state err) -> Result state err
-
-Description:
-Like [List.walk], but stops early and returns `Err` if the function returns `Err`.
-
-concat_utf8 : List U8, Str -> List U8
-
-Description:
-Concatenates the bytes of a string encoded as utf8 to a list of bytes.
-```roc
-expect List.concat_utf8([1, 2, 3, 4], "๐Ÿฆ") == [1, 2, 3, 4, 240, 159, 144, 166]
-```
-
-for_each! : List a, (a => {}) => {}
-
-Description:
-Run an effectful function for each element on the list.
-
-```roc
-List.for_each!(["Alice", "Bob", "Charlie"], |name|
-    create_account!(name)
-    log!("Account created")
-)
-```
-
-If the function might fail or you need to return early, use [for_each_try!].
-
-for_each_try! : List a, (a => Result {} err) => Result {} err
-
-Description:
-Run an effectful function that might fail for each element on the list.
-
-If the function returns `Err`, the iteration stops and the error is returned.
-
-```roc
-List.for_each_try!(files_to_delete, |path|
-    File.delete!(path)?
-
-    Stdout.line!("${path} deleted")
-)
-```
-
-walk! : List elem, state, (state, elem => state) => state
-
-Description:
-Build a value from the contents of a list, using an effectful function.
-
-```roc
-now_multiples = List.walk!([1, 2, 3], [], |nums, i|
-     now = Utc.now!({}) |> Utc.to_millis_since_epoch
-     List.append(nums, now * i)
-)
-```
-
-This is the same as [walk], except that the step function can have effects.
-
-walk_try! : List elem, state, (state, elem => Result state err) => Result state err
-
-Description:
-Build a value from the contents of a list, using an effectful function that might fail.
-
-If the function returns `Err`, the iteration stops and the error is returned.
-
-```
-names =
-    List.walk_try!(
-        ["First", "Middle", "Last"],
-        [],
-        |accumulator, which|
-            Stdout.write!("${which} name: ")?
-            name = Stdin.line!({})?
-            Ok(List.append(accumulator, name)),
-    )?
-```
-
-This is the same as [walk_try], except that the step function can have effects.
-
-### Dict
-
-Associative array mapping keys to values. Maintains insertion order for [Dict.keys]/[Dict.values], but [Dict.remove] moves last element into removed slot (O(1) removal). Based on IndexMap/unordered_dense.
-```roc
-Dict.empty({}) |> Dict.insert("London", 8_961_989) |> Dict.get("London")  # Ok(8_961_989)
-```
-
-empty : {} -> Dict * *
-
-Description:
-Return an empty dictionary.
-```roc
-empty_dict = Dict.empty({})
-```
-
-with_capacity : U64 -> Dict * *
-
-Description:
-Return a dictionary with space allocated for a number of entries. This
-may provide a performance optimization if you know how many entries will be
-inserted.
-
-reserve : Dict k v, U64 -> Dict k v
-
-Description:
-Enlarge the dictionary for at least capacity additional elements
-
-release_excess_capacity : Dict k v -> Dict k v
-
-Description:
-Shrink the memory footprint of a dictionary such that capacity is as small as possible.
-This function will require regenerating the metadata if the size changes.
-There will still be some overhead due to dictionary metadata always being a power of 2.
-
-capacity : Dict * * -> U64
-
-Description:
-Returns the max number of elements the dictionary can hold before requiring a rehash.
-```roc
-food_dict =
-    Dict.empty({})
-    |> Dict.insert("apple", "fruit")
-
-capacity_of_dict = Dict.capacity(food_dict)
-```
-
-single : k, v -> Dict k v
-
-Description:
-Returns a dictionary containing the key and value provided as input.
-```roc
-expect
-    Dict.single("A", "B")
-    |> Bool.is_eq(Dict.empty({}) |> Dict.insert("A", "B"))
-```
-
-from_list : List ( k, v ) -> Dict k v
-
-Description:
-Returns dictionary with the keys and values specified by the input [List].
-```roc
-expect
-    Dict.single(1, "One")
-    |> Dict.insert(2, "Two")
-    |> Dict.insert(3, "Three")
-    |> Dict.insert(4, "Four")
-    |> Bool.is_eq(Dict.from_list([(1, "One"), (2, "Two"), (3, "Three"), (4, "Four")]))
-```
-
-## Performance Details
-
-This will build up from an empty dictionary to minimize totally memory use.
-If the list has few duplicate keys, it would be faster to allocate a dictionary
-with the same capacity of the list and walk it calling [Dict.insert]
-
-len : Dict * * -> U64
-
-Description:
-Returns the number of values in the dictionary.
-```roc
-expect
-    Dict.empty({})
-    |> Dict.insert("One", "A Song")
-    |> Dict.insert("Two", "Candy Canes")
-    |> Dict.insert("Three", "Boughs of Holly")
-    |> Dict.len
-    |> Bool.is_eq(3)
-```
-
-is_empty : Dict * * -> Bool
-
-Description:
-Check if the dictionary is empty.
-```roc
-Dict.is_empty(Dict.empty({}) |> Dict.insert("key", 42))
-
-Dict.is_empty(Dict.empty({}))
-```
-
-clear : Dict k v -> Dict k v
-
-Description:
-Clears all elements from a dictionary keeping around the allocation if it isn't huge.
-```roc
-songs =
-       Dict.empty({})
-       |> Dict.insert("One", "A Song")
-       |> Dict.insert("Two", "Candy Canes")
-       |> Dict.insert("Three", "Boughs of Holly")
-
-clear_songs = Dict.clear(songs)
-
-expect Dict.len(clear_songs) == 0
-```
-
-map : Dict k a, (k, a -> b) -> Dict k b
-
-Description:
-Convert each value in the dictionary to something new, by calling a conversion
-function on each of them which receives both the key and the old value. Then return a
-new dictionary containing the same keys and the converted values.
-
-join_map : Dict a b, (a, b -> Dict x y) -> Dict x y
-
-Description:
-Like [Dict.map], except the transformation function wraps the return value
-in a dictionary. At the end, all the dictionaries get joined together
-(using [Dict.insert_all]) into one dictionary.
-
-You may know a similar function named `concat_map` in other languages.
-
-walk : Dict k v, state, (state, k, v -> state) -> state
-
-Description:
-Iterate through the keys and values in the dictionary and call the provided
-function with signature `state, k, v -> state` for each value, with an
-initial `state` value provided for the first call.
-```roc
-expect
-    Dict.empty({})
-    |> Dict.insert("Apples", 12)
-    |> Dict.insert("Orange", 24)
-    |> Dict.walk(0, (\count, _, qty -> count + qty))
-    |> Bool.is_eq(36)
-```
-
-walk_until : Dict k v, state, (state, k, v -> [ Continue state, Break state ]) -> state
-
-Description:
-Like [Dict.walk], but can stop early by returning `Break state`.
-
-keep_if : Dict k v, ( ( k, v ) -> Bool) -> Dict k v
-
-Description:
-Run the given function on each key-value pair of a dictionary, and return
-a dictionary with just the pairs for which the function returned `Bool.true`.
-```roc
-expect Dict.empty({})
-    |> Dict.insert("Alice", 17)
-    |> Dict.insert("Bob", 18)
-    |> Dict.insert("Charlie", 19)
-    |> Dict.keep_if(\(_k, v) -> v >= 18)
-    |> Dict.len
-    |> Bool.is_eq(2)
-```
-
-drop_if : Dict k v, ( ( k, v ) -> Bool) -> Dict k v
-
-Description:
-Run the given function on each key-value pair of a dictionary, and return
-a dictionary with just the pairs for which the function returned `Bool.false`.
-```roc
-expect Dict.empty({})
-    |> Dict.insert("Alice", 17)
-    |> Dict.insert("Bob", 18)
-    |> Dict.insert("Charlie", 19)
-    |> Dict.drop_if(\(_k, v) -> v >= 18)
-    |> Dict.len
-    |> Bool.is_eq(1)
-```
-
-get : Dict k v, k -> Result v [KeyNotFound]
-
-Description:
-Get the value for a given key. If there is a value for the specified key it
-will return [Ok value], otherwise return [Err KeyNotFound].
-```roc
-dictionary =
-    Dict.empty({})
-    |> Dict.insert(1,s "Apple")
-    |> Dict.insert(2,s "Orange")
-
-expect Dict.get(dictionary, 1) == Ok("Apple")
-expect Dict.get(dictionary, 2000) == Err(KeyNotFound)
-```
-
-contains : Dict k v, k -> Bool
-
-Description:
-Check if the dictionary has a value for a specified key.
-```roc
-expect
-    Dict.empty({})
-    |> Dict.insert(1234, "5678")
-    |> Dict.contains(1234)
-    |> Bool.is_eq(Bool.true)
-```
-
-insert : Dict k v, k, v -> Dict k v
-
-Description:
-Insert a value into the dictionary at a specified key.
-```roc
-expect
-    Dict.empty({})
-    |> Dict.insert("Apples", 12)
-    |> Dict.get("Apples")
-    |> Bool.is_eq(Ok(12))
-```
-
-remove : Dict k v, k -> Dict k v
-
-Description:
-Remove a value from the dictionary for a specified key.
-```roc
-expect
-    Dict.empty({})
-    |> Dict.insert("Some", "Value")
-    |> Dict.remove("Some")
-    |> Dict.len
-    |> Bool.is_eq(0)
-```
-
-update : Dict k v, k, (Result v [Missing] -> Result v [Missing]) -> Dict k v
-
-Description:
-Insert or remove a value for a specified key. This function enables a
-performance optimization for the use case of providing a default when a value
-is missing. This is more efficient than doing both a `Dict.get` and then a
-`Dict.insert` call, and supports being piped.
-```roc
-alter_value : Result Bool [Missing] -> Result Bool [Missing]
-alter_value = \possible_value ->
-    when possible_value is
-        Err Missing -> Ok(Bool.false)
-        Ok value -> if value then Err(Missing) else Ok(Bool.true)
-
-expect Dict.update(Dict.empty({}), "a", alter_value) == Dict.single("a", Bool.false)
-expect Dict.update(Dict.single("a", Bool.false), "a", alter_value) == Dict.single("a", Bool.true)
-expect Dict.update(Dict.single("a", Bool.true), "a", alter_value) == Dict.empty({})
-```
-
-to_list : Dict k v -> List ( k, v )
-
-Description:
-Returns the keys and values of a dictionary as a [List].
-This requires allocating a temporary list, prefer using [Dict.to_list] or [Dict.walk] instead.
-```roc
-expect
-    Dict.single(1, "One")
-    |> Dict.insert(2, "Two")
-    |> Dict.insert(3, "Three")
-    |> Dict.insert(4, "Four")
-    |> Dict.to_list
-    |> Bool.is_eq([(1, "One"), (2, "Two"), (3, "Three"), (4, "Four")])
-```
-
-keys : Dict k v -> List k
-
-Description:
-Returns the keys of a dictionary as a [List].
-This requires allocating a temporary [List], prefer using [Dict.to_list] or [Dict.walk] instead.
-```roc
-expect
-    Dict.single(1, "One")
-    |> Dict.insert(2, "Two")
-    |> Dict.insert(3, "Three")
-    |> Dict.insert(4, "Four")
-    |> Dict.keys
-    |> Bool.is_eq([1,2,3,4])
-```
-
-values : Dict k v -> List v
-
-Description:
-Returns the values of a dictionary as a [List].
-This requires allocating a temporary [List], prefer using [Dict.to_list] or [Dict.walk] instead.
-```roc
-expect
-    Dict.single(1, "One")
-    |> Dict.insert(2, "Two")
-    |> Dict.insert(3, "Three")
-    |> Dict.insert(4, "Four")
-    |> Dict.values
-    |> Bool.is_eq(["One","Two","Three","Four"])
-```
-
-insert_all : Dict k v, Dict k v -> Dict k v
-
-Description:
-Combine two dictionaries by keeping the [union](https://en.wikipedia.org/wiki/Union_(set_theory))
-of all the key-value pairs. This means that all the key-value pairs in
-both dictionaries will be combined. Note that where there are pairs
-with the same key, the value contained in the second input will be
-retained, and the value in the first input will be removed.
-```roc
-first =
-    Dict.single(1, "Not Me")
-    |> Dict.insert(2, "And Me")
-
-second =
-    Dict.single(1, "Keep Me")
-    |> Dict.insert(3, "Me Too")
-    |> Dict.insert(4, "And Also Me")
-
-expected =
-    Dict.single(1, "Keep Me")
-    |> Dict.insert(2, "And Me")
-    |> Dict.insert(3, "Me Too")
-    |> Dict.insert(4, "And Also Me")
-
-expect
-    Dict.insert_all(first, second) == expected
-```
-
-keep_shared : Dict k v, Dict k v -> Dict k v where v implements Eq
-
-Description:
-Combine two dictionaries by keeping the [intersection](https://en.wikipedia.org/wiki/Intersection_(set_theory))
-of all the key-value pairs. This means that we keep only those pairs
-that are in both dictionaries. Both the key and value must match to be kept.
-```roc
-first =
-    Dict.single(1, "Keep Me")
-    |> Dict.insert(2, "And Me")
-    |> Dict.insert(3, "Not this one")
-
-second =
-    Dict.single(1, "Keep Me")
-    |> Dict.insert(2, "And Me")
-    |> Dict.insert(3, "This has a different value")
-    |> Dict.insert(4, "Or Me")
-
-expected =
-    Dict.single(1, "Keep Me")
-    |> Dict.insert(2, "And Me")
-
-expect Dict.keep_shared(first, second) == expected
-```
-
-remove_all : Dict k v, Dict k v -> Dict k v
-
-Description:
-Remove the key-value pairs in the first input that are also in the second
-using the [set difference](https://en.wikipedia.org/wiki/Complement_(set_theory)#Relative_complement)
-of the values. This means that we will be left with only those pairs that
-are in the first dictionary and whose keys are not in the second.
-```roc
-first =
-    Dict.single(1, "Keep Me")
-    |> Dict.insert(2, "And Me")
-    |> Dict.insert(3, "Remove Me")
-
-second =
-    Dict.single(3, "Remove Me")
-    |> Dict.insert(4, "I do nothing...")
-
-expected =
-    Dict.single(1, "Keep Me")
-    |> Dict.insert(2, "And Me")
-
-expect Dict.remove_all(first, second) == expected
-```
-
-### Set
-
-Description:
-Provides a [set](https://en.wikipedia.org/wiki/Set_(abstract_data_type))
-type which stores a collection of unique values, without any ordering
-
-empty : {} -> Set *
-
-Description:
-Creates a new empty `Set`.
-```roc
-empty_set = Set.empty({})
-count_values = Set.len(empty_set)
-
-expect count_values == 0
-```
-
-with_capacity : U64 -> Set *
-
-Description:
-Return a set with space allocated for a number of entries. This
-may provide a performance optimization if you know how many entries will be
-inserted.
-
-reserve : Set k, U64 -> Set k
-
-Description:
-Enlarge the set for at least capacity additional elements
-
-release_excess_capacity : Set k -> Set k
-
-Description:
-Shrink the memory footprint of a set such that capacity is as small as possible.
-This function will require regenerating the metadata if the size changes.
-There will still be some overhead due to dictionary metadata always being a power of 2.
-
-single : k -> Set k
-
-Description:
-Creates a new `Set` with a single value.
-```roc
-single_item_set = Set.single("Apple")
-count_values = Set.len(single_item_set)
-
-expect count_values == 1
-```
-
-insert : Set k, k -> Set k
-
-Description:
-Insert a value into a `Set`.
-```roc
-few_item_set =
-    Set.empty({})
-    |> Set.insert("Apple")
-    |> Set.insert("Pear")
-    |> Set.insert("Banana")
-
-count_values = Set.len(few_item_set)
-
-expect count_values == 3
-```
-
-len : Set * -> U64
-
-Description:
-Counts the number of values in a given `Set`.
-```roc
-few_item_set =
-    Set.empty({})
-    |> Set.insert("Apple")
-    |> Set.insert("Pear")
-    |> Set.insert("Banana")
-
-count_values = Set.len(few_item_set)
-
-expect count_values == 3
-```
-
-capacity : Set * -> U64
-
-Description:
-Returns the max number of elements the set can hold before requiring a rehash.
-```roc
-food_set =
-    Set.empty({})
-    |> Set.insert("apple")
-
-capacity_of_set = Set.capacity(food_set)
-```
-
-is_empty : Set * -> Bool
-
-Description:
-Check if the set is empty.
-```roc
-Set.is_empty(Set.empty({}) |> Set.insert(42))
-
-Set.is_empty(Set.empty({}))
-```
-
-remove : Set k, k -> Set k
-
-Description:
-Removes the value from the given `Set`.
-```roc
-numbers =
-    Set.empty({})
-    |> Set.insert(10)
-    |> Set.insert(20)
-    |> Set.remove(10)
-
-has10 = Set.contains(numbers, 10)
-has20 = Set.contains(numbers, 20)
-
-expect has10 == Bool.false
-expect has20 == Bool.true
-```
-
-contains : Set k, k -> Bool
-
-Description:
-Test if a value is in the `Set`.
-```roc
-Fruit : [Apple, Pear, Banana]
-
-fruit : Set Fruit
-fruit =
-    Set.single(Apple)
-    |> Set.insert(Pear)
-
-has_apple = Set.contains(fruit, Apple)
-has_banana = Set.contains(fruit, Banana)
-
-expect has_apple == Bool.true
-expect has_banana == Bool.false
-```
-
-to_list : Set k -> List k
-
-Description:
-Retrieve the values in a `Set` as a `List`.
-```roc
-numbers : Set U64
-numbers = Set.from_list([1,2,3,4,5])
-
-values = [1,2,3,4,5]
-
-expect Set.to_list(numbers) == values
-```
-
-from_list : List k -> Set k
-
-Description:
-Create a `Set` from a `List` of values.
-```roc
-values =
-    Set.empty({})
-    |> Set.insert(Banana)
-    |> Set.insert(Apple)
-    |> Set.insert(Pear)
-
-expect Set.from_list([Pear, Apple, Banana]) == values
-```
-
-union : Set k, Set k -> Set k
-
-Description:
-Combine two `Set` collection by keeping the
-[union](https://en.wikipedia.org/wiki/Union_(set_theory))
-of all the values pairs. This means that all of the values in both `Set`s
-will be combined.
-```roc
-set1 = Set.single(Left)
-set2 = Set.single(Right)
-
-expect Set.union(set1, set2) == Set.from_list([Left, Right])
-```
-
-intersection : Set k, Set k -> Set k
-
-Description:
-Combine two `Set`s by keeping the [intersection](https://en.wikipedia.org/wiki/Intersection_(set_theory))
-of all the values pairs. This means that we keep only those values that are
-in both `Set`s.
-```roc
-set1 = Set.from_list([Left, Other])
-set2 = Set.from_list([Left, Right])
-
-expect Set.intersection(set1, set2) == Set.single(Left)
-```
-
-difference : Set k, Set k -> Set k
-
-Description:
-Remove the values in the first `Set` that are also in the second `Set`
-using the [set difference](https://en.wikipedia.org/wiki/Complement_(set_theory)#Relative_complement)
-of the values. This means that we will be left with only those values that
-are in the first and not in the second.
-```roc
-first = Set.from_list([Left, Right, Up, Down])
-second = Set.from_list([Left, Right])
-
-expect Set.difference(first, second) == Set.from_list([Up, Down])
-```
-
-walk : Set k, state, (state, k -> state) -> state
-
-Description:
-Iterate through the values of a given `Set` and build a value.
-```roc
-values = Set.from_list(["March", "April", "May"])
-
-starts_with_letter_m = \month ->
-    when Str.to_utf8(month) is
-        ['M', ..] -> Bool.true
-        _ -> Bool.false
-
-reduce = \state, k ->
-    if starts_with_letter_m(k) then
-        state + 1
-    else
-        state
-
-result = Set.walk(values, 0, reduce)
-
-expect result == 2
-```
-
-map : Set a, (a -> b) -> Set b
-
-Description:
-Convert each value in the set to something new, by calling a conversion
-function on each of them which receives the old value. Then return a
-new set containing the converted values.
-
-join_map : Set a, (a -> Set b) -> Set b
-
-Description:
-Like [Set.map], except the transformation function wraps the return value
-in a set. At the end, all the sets get joined together
-(using [Set.union]) into one set.
-
-You may know a similar function named `concat_map` in other languages.
-
-walk_until : Set k, state, (state, k -> [ Continue state, Break state ]) -> state
-
-Description:
-Iterate through the values of a given `Set` and build a value, can stop
-iterating part way through the collection.
-```roc
-numbers = Set.from_list([1,2,3,4,5,6,42,7,8,9,10])
-
-find42 = \state, k ->
-    if k == 42 then
-        Break(FoundTheAnswer)
-    else
-        Continue(state)
-
-result = Set.walk_until(numbers, NotFound, find42)
-
-expect result == FoundTheAnswer
-```
-
-keep_if : Set k, (k -> Bool) -> Set k
-
-Description:
-Run the given function on each element in the `Set`, and return
-a `Set` with just the elements for which the function returned `Bool.true`.
-```roc
-expect Set.from_list([1,2,3,4,5])
-    |> Set.keep_if(\k -> k >= 3)
-    |> Bool.is_eq(Set.from_list([3,4,5]))
-```
-
-drop_if : Set k, (k -> Bool) -> Set k
-
-Description:
-Run the given function on each element in the `Set`, and return
-a `Set` with just the elements for which the function returned `Bool.false`.
-```roc
-expect Set.from_list [1,2,3,4,5]
-    |> Set.drop_if(\k -> k >= 3)
-    |> Bool.is_eq(Set.from_list([1,2]))
-```
-
-### Decode
-
-DecodeError : [TooShort]
-
-Description:
-Error types when decoding a `List U8` of utf-8 bytes using a [Decoder]
-
-Description:
-Return type of a [Decoder].
-
-This can be useful when creating a [custom](#custom) decoder or when
-using [from_bytes_partial](#from_bytes_partial). For example writing unit tests,
-such as;
-```roc
-expect
-    input = "\"hello\", " |> Str.to_utf8
-    actual = Decode.from_bytes_partial(input, Json.json)
-    expected = Ok("hello")
-
-    actual.result == expected
-```
-
-Description:
-Decodes a `List U8` of utf-8 bytes where `val` is the type of the decoded
-value, and `fmt` is a [Decoder] which implements the [DecoderFormatting]
-ability
-
-Decoding : implements
-    decoder : Decoder val fmt
-        where val implements Decoding, fmt implements DecoderFormatting
-
-Description:
-Definition of the [Decoding] ability
-
-DecoderFormatting : implements
-    u8 : Decoder U8 fmt
-        where fmt implements DecoderFormatting
-    u16 : Decoder U16 fmt
-        where fmt implements DecoderFormatting
-    u32 : Decoder U32 fmt
-        where fmt implements DecoderFormatting
-    u64 : Decoder U64 fmt
-        where fmt implements DecoderFormatting
-    u128 : Decoder U128 fmt
-        where fmt implements DecoderFormatting
-    i8 : Decoder I8 fmt
-        where fmt implements DecoderFormatting
-    i16 : Decoder I16 fmt
-        where fmt implements DecoderFormatting
-    i32 : Decoder I32 fmt
-        where fmt implements DecoderFormatting
-    i64 : Decoder I64 fmt
-        where fmt implements DecoderFormatting
-    i128 : Decoder I128 fmt
-        where fmt implements DecoderFormatting
-    f32 : Decoder F32 fmt
-        where fmt implements DecoderFormatting
-    f64 : Decoder F64 fmt
-        where fmt implements DecoderFormatting
-    dec : Decoder Dec fmt
-        where fmt implements DecoderFormatting
-    bool : Decoder Bool fmt
-        where fmt implements DecoderFormatting
-    string : Decoder Str fmt
-        where fmt implements DecoderFormatting
-    list : Decoder elem fmt -> Decoder (List elem) fmt
-        where fmt implements DecoderFormatting
-    record : 
-        state,         
-        (state, 
-        Str
-        -> 
-            [
-                Keep (Decoder state fmt),
-                Skip
-            ]), 
-        (state, fmt -> Result val DecodeError)
-        -> Decoder val fmt
-        where fmt implements DecoderFormatting
-    tuple : 
-        state,         
-        (state, 
-        U64
-        -> 
-            [
-                Next (Decoder state fmt),
-                TooLong
-            ]), 
-        (state -> Result val DecodeError)
-        -> Decoder val fmt
-        where fmt implements DecoderFormatting
-
-Description:
-Definition of the [DecoderFormatting] ability
-
-custom : (List U8, fmt -> DecodeResult val) -> Decoder val fmt where fmt implements DecoderFormatting
-
-Description:
-Build a custom [Decoder] function. For example the implementation of
-`decode_bool` could be defined as follows;
-
-```roc
-decode_bool = Decode.custom \bytes, @Json({}) ->
-    when bytes is
-        ['f', 'a', 'l', 's', 'e', ..] -> { result: Ok(Bool.false), rest: List.drop_first(bytes, 5) }
-        ['t', 'r', 'u', 'e', ..] -> { result: Ok Bool.true, rest: List.drop_first(bytes, 4) }
-        _ -> { result: Err(TooShort), rest: bytes }
-```
-
-decode_with : List U8, Decoder val fmt, fmt -> DecodeResult val where fmt implements DecoderFormatting
-
-Description:
-Decode a `List U8` utf-8 bytes using a specific [Decoder] function
-
-from_bytes_partial : List U8, fmt -> DecodeResult val where val implements Decoding, fmt implements DecoderFormatting
-
-Description:
-Decode a `List U8` utf-8 bytes and return a [DecodeResult](#DecodeResult)
-```roc
-expect
-    input = "\"hello\", " |> Str.to_utf8
-    actual = Decode.from_bytes_partial(input Json.json)
-    expected = Ok("hello")
-
-    actual.result == expected
-```
-
-from_bytes : List U8, fmt -> Result val [Leftover (List U8)]DecodeError where val implements Decoding, fmt implements DecoderFormatting
-
-Description:
-Decode a `List U8` utf-8 bytes and return a [Result] with no leftover bytes
-expected. If successful returns `Ok val`, however, if there are bytes
-remaining returns `Err Leftover (List U8)`.
-```roc
-expect
-    input = "\"hello\", " |> Str.to_utf8
-    actual = Decode.from_bytes(input, Json.json)
-    expected = Ok("hello")
-
-    actual == expected
-```
-
-map_result : DecodeResult a, (a -> b) -> DecodeResult b
-
-Description:
-Transform the `val` of a [DecodeResult]
-
-### Encode
-
-Encoding : implements
-    to_encoder : val -> Encoder fmt
-        where val implements Encoding, fmt implements EncoderFormatting
-
-EncoderFormatting : implements
-    u8 : U8 -> Encoder fmt
-        where fmt implements EncoderFormatting
-    u16 : U16 -> Encoder fmt
-        where fmt implements EncoderFormatting
-    u32 : U32 -> Encoder fmt
-        where fmt implements EncoderFormatting
-    u64 : U64 -> Encoder fmt
-        where fmt implements EncoderFormatting
-    u128 : U128 -> Encoder fmt
-        where fmt implements EncoderFormatting
-    i8 : I8 -> Encoder fmt
-        where fmt implements EncoderFormatting
-    i16 : I16 -> Encoder fmt
-        where fmt implements EncoderFormatting
-    i32 : I32 -> Encoder fmt
-        where fmt implements EncoderFormatting
-    i64 : I64 -> Encoder fmt
-        where fmt implements EncoderFormatting
-    i128 : I128 -> Encoder fmt
-        where fmt implements EncoderFormatting
-    f32 : F32 -> Encoder fmt
-        where fmt implements EncoderFormatting
-    f64 : F64 -> Encoder fmt
-        where fmt implements EncoderFormatting
-    dec : Dec -> Encoder fmt
-        where fmt implements EncoderFormatting
-    bool : Bool -> Encoder fmt
-        where fmt implements EncoderFormatting
-    string : Str -> Encoder fmt
-        where fmt implements EncoderFormatting
-    list : List elem, (elem -> Encoder fmt) -> Encoder fmt
-        where fmt implements EncoderFormatting
-    record :         List 
-        {
-            key : Str,
-            value : Encoder fmt
-        }
-        -> Encoder fmt
-        where fmt implements EncoderFormatting
-    tuple : List (Encoder fmt) -> Encoder fmt
-        where fmt implements EncoderFormatting
-    tag : Str, List (Encoder fmt) -> Encoder fmt
-        where fmt implements EncoderFormatting
-
-custom : (List U8, fmt -> List U8) -> Encoder fmt where fmt implements EncoderFormatting
-
-Description:
-Creates a custom encoder from a given function.
-
-```roc
-expect
-    # Appends the byte 42
-    custom_encoder = Encode.custom(\bytes, _fmt -> List.append(bytes, 42))
-
-    actual = Encode.append_with([], custom_encoder, Core.json)
-    expected = [42] # Expected result is a list with a single byte, 42
-
-    actual == expected
-```
-
-append_with : List U8, Encoder fmt, fmt -> List U8 where fmt implements EncoderFormatting
-
-append : List U8, val, fmt -> List U8 where val implements Encoding, fmt implements EncoderFormatting
-
-Description:
-Appends the encoded representation of a value to an existing list of bytes.
-
-```roc
-expect
-    actual = Encode.append([], { foo: 43 }, Core.json)
-    expected = Str.to_utf8("""{"foo":43}""")
-
-    actual == expected
-```
-
-to_bytes : val, fmt -> List U8 where val implements Encoding, fmt implements EncoderFormatting
-
-Description:
-Encodes a value to a list of bytes (`List U8`) according to the specified format.
-
-```roc
-expect
-    foo_rec = { foo: 42 }
-
-    actual = Encode.to_bytes(foo_rec, Core.json)
-    expected = Str.to_utf8("""{"foo":42}""")
-
-    actual == expected
-```
-
-### Hash
-
-Hash : implements
-    hash : hasher, a -> hasher
-        where a implements Hash, hasher implements Hasher
-
-Description:
-A value that can be hashed.
-
-Hasher : implements
-    add_bytes : a, List U8 -> a
-        where a implements Hasher
-    add_u8 : a, U8 -> a
-        where a implements Hasher
-    add_u16 : a, U16 -> a
-        where a implements Hasher
-    add_u32 : a, U32 -> a
-        where a implements Hasher
-    add_u64 : a, U64 -> a
-        where a implements Hasher
-    add_u128 : a, U128 -> a
-        where a implements Hasher
-    complete : a -> U64
-        where a implements Hasher
-
-Description:
-Describes a hashing algorithm that is fed bytes and produces an integer hash.
-
-The [Hasher] ability describes general-purpose hashers. It only allows
-emission of 64-bit unsigned integer hashes. It is not suitable for
-cryptographically-secure hashing.
-
-Description:
-Adds a string into a [Hasher] by hashing its UTF-8 bytes.
-
-Description:
-Adds a list of [Hash]able elements to a [Hasher] by hashing each element.
-
-hash_bool : a, Bool -> a where a implements Hasher
-
-Description:
-Adds a single [Bool] to a hasher.
-
-hash_i8 : a, I8 -> a where a implements Hasher
-
-Description:
-Adds a single I8 to a hasher.
-
-hash_i16 : a, I16 -> a where a implements Hasher
-
-Description:
-Adds a single I16 to a hasher.
-
-hash_i32 : a, I32 -> a where a implements Hasher
-
-Description:
-Adds a single I32 to a hasher.
-
-hash_i64 : a, I64 -> a where a implements Hasher
-
-Description:
-Adds a single I64 to a hasher.
-
-hash_i128 : a, I128 -> a where a implements Hasher
-
-Description:
-Adds a single I128 to a hasher.
-
-hash_dec : a, Dec -> a where a implements Hasher
-
-Description:
-Adds a single [Dec] to a hasher.
-
-Description:
-Adds a container of [Hash]able elements to a [Hasher] by hashing each element.
-The container is iterated using the walk method passed in.
-The order of the elements does not affect the final hash.
-
-### Box
-
-box : a -> Box a
-
-Description:
-Allocates a value on the heap. Boxing is an expensive process as it copies
-the value from the stack to the heap. This may provide a performance
-optimization for advanced use cases with large values. A platform may require
-that some values are boxed.
-```roc
-expect Box.unbox(Box.box("Stack Faster")) == "Stack Faster"
-```
-
-unbox : Box a -> a
-
-Description:
-Returns a boxed value.
-```roc
-expect Box.unbox(Box.box("Stack Faster") == "Stack Faster"
-```
-
-### Inspect
-
-KeyValWalker : collection, state, (state, key, val -> state) -> state
-
-ElemWalker : collection, state, (state, elem -> state) -> state
-
-InspectFormatter : implements
-    init : {} -> f
-        where f implements InspectFormatter
-    tag : Str, List (Inspector f) -> Inspector f
-        where f implements InspectFormatter
-    tuple : List (Inspector f) -> Inspector f
-        where f implements InspectFormatter
-    record :         List 
-        {
-            key : Str,
-            value : Inspector f
-        }
-        -> Inspector f
-        where f implements InspectFormatter
-    bool : Bool -> Inspector f
-        where f implements InspectFormatter
-    str : Str -> Inspector f
-        where f implements InspectFormatter
-    list : 
-        list, 
-        ElemWalker state list elem, 
-        (elem -> Inspector f)
-        -> Inspector f
-        where f implements InspectFormatter
-    set : 
-        set, 
-        ElemWalker state set elem, 
-        (elem -> Inspector f)
-        -> Inspector f
-        where f implements InspectFormatter
-    dict : 
-        dict, 
-        KeyValWalker state dict key value, 
-        (key -> Inspector f), 
-        (value -> Inspector f)
-        -> Inspector f
-        where f implements InspectFormatter
-    opaque : * -> Inspector f
-        where f implements InspectFormatter
-    function : * -> Inspector f
-        where f implements InspectFormatter
-    u8 : U8 -> Inspector f
-        where f implements InspectFormatter
-    i8 : I8 -> Inspector f
-        where f implements InspectFormatter
-    u16 : U16 -> Inspector f
-        where f implements InspectFormatter
-    i16 : I16 -> Inspector f
-        where f implements InspectFormatter
-    u32 : U32 -> Inspector f
-        where f implements InspectFormatter
-    i32 : I32 -> Inspector f
-        where f implements InspectFormatter
-    u64 : U64 -> Inspector f
-        where f implements InspectFormatter
-    i64 : I64 -> Inspector f
-        where f implements InspectFormatter
-    u128 : U128 -> Inspector f
-        where f implements InspectFormatter
-    i128 : I128 -> Inspector f
-        where f implements InspectFormatter
-    f32 : F32 -> Inspector f
-        where f implements InspectFormatter
-    f64 : F64 -> Inspector f
-        where f implements InspectFormatter
-    dec : Dec -> Inspector f
-        where f implements InspectFormatter
-
-custom : (f -> f) -> Inspector f where f implements InspectFormatter
-
-apply : Inspector f, f -> f where f implements InspectFormatter
-
-Inspect : implements
-    to_inspector : val -> Inspector f
-        where val implements Inspect, f implements InspectFormatter
-
-inspect : val -> f where val implements Inspect, f implements InspectFormatter
-
-to_str : val -> Str where val implements Inspect
-

skills/writing-roc-lang/references/llms.md ๐Ÿ”—

@@ -1,707 +0,0 @@
-# Roc Language Reference
-
-## REPL
-
-Run with `roc repl`. Online: [roc-lang.org/repl](https://www.roc-lang.org/repl)
-
-```roc
-greeting = "Hi"
-audience = "World"
-```
-
-Arithmetic: `1 + 2 * (3 - 4)` follows order of operations.
-
-## Calling Functions
-
-```roc
-Str.concat("Hi ", "there.")  # "Hi there."
-```
-
-`Str` is a module, `concat` is a function in that module.
-
-### String Interpolation
-
-```roc
-"${greeting} there, ${audience}."
-"Two plus three is: ${Num.to_str(2 + 3)}"
-```
-
-## Building an Application
-
-```roc
-app [main!] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.20.0/X73hGh05nNTkDHU06FHC0YfFaQB1pimX7gncRcao5mU.tar.br" }
-
-import pf.Stdout
-
-main! = |_args|
-    Stdout.line!("Hi there, from inside a Roc app. ๐ŸŽ‰")
-```
-
-Run: `roc main.roc`
-
-### Defs
-
-```roc
-birds = 3
-iguanas = 2
-total = Num.to_str(birds + iguanas)
-
-main! = |_args|
-    Stdout.line!("There are ${total} animals.")
-```
-
-Defs are constantโ€”cannot be reassigned.
-
-### Defining Functions
-
-```roc
-add_and_stringify = |num1, num2|
-    Num.to_str(num1 + num2)
-```
-
-### if-then-else
-
-```roc
-add_and_stringify = |num1, num2|
-    sum = num1 + num2
-    if sum == 0 then
-        ""
-    else if sum < 0 then
-        "negative"
-    else
-        Num.to_str(sum)
-```
-
-Every `if` must have both `then` and `else`.
-
-### Comments
-
-```roc
-# Single line comment
-## Doc comment (included in generated docs)
-##     x = 2  # Code block in doc (5 spaces after ##)
-```
-
-### Records
-
-```roc
-add_and_stringify = |counts|
-    Num.to_str(counts.birds + counts.iguanas)
-
-total = add_and_stringify({ birds: 5, iguanas: 7 })
-```
-
-Functions accept records with extra fields:
-
-```roc
-total_with_note = add_and_stringify({ birds: 4, iguanas: 3, note: "Whee!" })
-```
-
-### Record Shorthands
-
-```roc
-return_foo = .foo  # Same as |record| record.foo
-{ x: x, y: y }     # Same as { x, y }
-```
-
-### Record Destructuring
-
-```roc
-add_and_stringify = |{ birds, iguanas }|
-    Num.to_str(birds + iguanas)
-
-add_and_stringify = |{ birds, iguanas: lizards }|  # Rename field
-    Num.to_str(birds + lizards)
-
-{ x, y } = { x: 5, y: 10 }  # Destructure in defs
-```
-
-### Record Update
-
-```roc
-original = { birds: 5, zebras: 2, iguanas: 7, goats: 1 }
-from_original = { original & birds: 4, iguanas: 3 }
-```
-
-`&` cannot introduce new fields or change types.
-
-### Debugging with dbg
-
-```roc
-pluralize = |singular, plural, count|
-    dbg count  # Prints: [pluralize.roc 6:8] 5
-    if count == 1 then singular else plural
-
-dbg Str.concat(singular, plural)  # Any expression
-inc = |n| 1 + dbg n               # As function in expression
-```
-
-### Tuples
-
-```roc
-tuple = ("hello", 42, ["list"])
-first = tuple.0   # "hello"
-second = tuple.1  # 42
-
-(first, second, third) = ("hello", 42, ["list"])  # Destructuring
-```
-
-## Pattern Matching
-
-### Tags
-
-```roc
-stoplight_color =
-    if something > 0 then Red
-    else if something == 0 then Yellow
-    else Green
-```
-
-Tags are capitalized literals (like numbers/strings, no definition needed).
-
-### when/is
-
-```roc
-stoplight_str =
-    when stoplight_color is
-        Red -> "red"
-        Green -> "green"
-        Yellow -> "yellow"
-```
-
-Catch-all with `_`:
-
-```roc
-when stoplight_color is
-    Red -> "red"
-    _ -> "not red"
-```
-
-Multiple tags with `|`:
-
-```roc
-when stoplight_color is
-    Red -> "red"
-    Green | Yellow -> "not red"
-```
-
-Guards with `if`:
-
-```roc
-when stoplight_color is
-    Red -> "red"
-    Green | Yellow if contrast > 75 -> "high contrast"
-    Green | Yellow -> "not red"
-```
-
-### Tags with Payloads
-
-```roc
-stoplight_color =
-    if something > 100 then Red
-    else if something > 0 then Yellow
-    else Custom("some other color")
-
-stoplight_str =
-    when stoplight_color is
-        Red -> "red"
-        Green | Yellow -> "not red"
-        Custom(description) -> description
-```
-
-Multi-value payloads: `Custom(40, 60, 80)` destructured as `Custom(r, g, b) ->`
-
-### Booleans
-
-`Bool.true` and `Bool.false` (not keywords). Prefer tags for data modeling:
-
-```roc
-{ name: "Richard", role: Admin }  # Better than is_admin: Bool.true
-```
-
-## Lists
-
-```roc
-names = ["Sam", "Lee", "Ari"]
-List.append(names, "Jess")  # Returns new list (immutable)
-```
-
-### List.map
-
-```roc
-List.map([1, 2, 3], |num| num * 2)  # [2, 4, 6]
-List.map([1, 2, 3], Num.is_odd)     # [Bool.true, Bool.false, Bool.true]
-```
-
-All list elements must share a type. Use tags for mixed types:
-
-```roc
-List.map([StrElem "A", NumElem 1], |elem|
-    when elem is
-        NumElem(num) -> Num.is_negative(num)
-        StrElem(str) -> Str.starts_with(str, "A")
-)
-```
-
-### Using Tags as Functions
-
-```roc
-List.map(["a", "b", "c"], Foo)  # Same as |str| Foo(str)
-```
-
-### List.any / List.all
-
-```roc
-List.any([1, 2, 3], Num.is_odd)       # Bool.true
-List.all([1, 2, 3], Num.is_positive)  # Bool.true
-```
-
-### Removing Elements
-
-```roc
-List.drop_at(["Sam", "Lee", "Ari"], 1)  # ["Sam", "Ari"]
-List.keep_if([1, 2, 3, 4, 5], Num.is_even)  # [2, 4]
-List.drop_if([1, 2, 3, 4, 5], Num.is_even)  # [1, 3, 5]
-```
-
-### Getting Elements
-
-```roc
-List.get(["a", "b", "c"], 1)    # Ok "b"
-List.get(["a", "b", "c"], 100)  # Err(OutOfBounds)
-List.first(list)                # Err(ListWasEmpty) if empty
-List.last(list)                 # Err(ListWasEmpty) if empty
-```
-
-## Error Handling
-
-```roc
-Result.with_default(List.get(["a", "b", "c"], 100), "")  # ""
-Result.isOk(List.get(["a", "b", "c"], 1))  # Bool.true
-```
-
-### ? Postfix Operator
-
-Unwraps `Ok`, returns early on `Err`:
-
-```roc
-get_letter : Str -> Result Str [OutOfBounds, InvalidNumStr]
-get_letter = |index_str|
-    index = Str.to_u64(index_str)?
-    List.get(["a", "b", "c", "d"], index)
-```
-
-### ?? Infix Operator (Default on Error)
-
-```roc
-List.get(["a", "b", "c"], 100) ?? ""  # ""
-```
-
-### List.walk
-
-```roc
-List.walk([1, 2, 3, 4, 5], { evens: [], odds: [] }, |state, elem|
-    if Num.is_even(elem) then
-        { state & evens: List.append(state.evens, elem) }
-    else
-        { state & odds: List.append(state.odds, elem) }
-)
-# { evens: [2, 4], odds: [1, 3, 5] }
-```
-
-Arguments: list, initial state, function `(state, elem) -> state`
-
-### Pattern Matching on Lists
-
-```roc
-when my_list is
-    [] -> 0                      # empty
-    [Foo, ..] -> 1               # starts with Foo
-    [_, ..] -> 2                 # at least one element
-    [Foo, Bar, Baz] -> 3         # exactly 3 elements
-    [Foo, a, ..] -> 4            # second element named `a`
-    [Ok a, ..] -> 5              # first is Ok with payload
-    [.., Foo] -> 6               # ends with Foo
-    [A, B, .., C, D] -> 7        # specific start and end
-    [head, .. as tail] -> 8     # head and rest
-```
-
-Only one `..` (rest pattern) per pattern.
-
-### Pipe Operator
-
-```roc
-["a", "b", "c"] |> List.get(1) |> Result.with_default("")
-# Same as: Result.with_default(List.get(["a", "b", "c"], 1), "")
-```
-
-## Types
-
-### Type Annotations
-
-```roc
-full_name : Str, Str -> Str
-full_name = |first_name, last_name|
-    "${first_name} ${last_name}"
-
-first_name : Str
-first_name = "Amy"
-
-amy : { first_name : Str, last_name : Str }
-amy = { first_name: "Amy", last_name: "Lee" }
-```
-
-### Type Aliases
-
-```roc
-Musician : { first_name : Str, last_name : Str }
-
-amy : Musician
-amy = { first_name: "Amy", last_name: "Lee" }
-```
-
-### Type Parameters
-
-```roc
-names : List Str
-names = ["Amy", "Simone", "Tarja"]
-```
-
-### Wildcard Type (*)
-
-```roc
-is_empty : List * -> Bool  # Works on any list type
-```
-
-Empty list `[]` has type `List *`.
-
-### Type Variables
-
-```roc
-reverse : List elem -> List elem  # Same element type in and out
-```
-
-Lowercase names (`elem`, `a`, `value`) are type variables.
-
-### Tag Union Types
-
-```roc
-color_from_str : Str -> [Red, Green, Yellow]
-color_from_str = |string|
-    when string is
-        "red" -> Red
-        "green" -> Green
-        _ -> Yellow
-```
-
-Tag unions accumulate:
-
-```roc
-|str|
-    if Str.is_empty(str) then Ok "it was empty"
-    else Err ["it was not empty"]
-# Type: Str -> [Ok Str, Err (List Str)]
-```
-
-`Result ok err` is alias for `[Ok ok, Err err]`.
-
-### Opaque Types
-
-```roc
-Username := Str
-
-from_str : Str -> Username
-from_str = |str| @Username(str)
-
-to_str : Username -> Str
-to_str = |@Username(str)| str
-```
-
-`@Username` only usable in defining module.
-
-### Integers
-
-| Type | Range |
-|------|-------|
-| U8   | 0 to 255 |
-| I8   | -128 to 127 |
-| U16  | 0 to 65,535 |
-| I16  | -32,768 to 32,767 |
-| U32  | 0 to 4,294,967,295 |
-| I32  | -2,147,483,648 to 2,147,483,647 |
-| U64  | 0 to 18+ quintillion |
-| I64  | -9+ to 9+ quintillion |
-| U128 | 0 to 340+ undecillion |
-| I128 | ยฑ170+ undecillion |
-
-Overflow crashes the program.
-
-### Fractions
-
-| Type | Description |
-|------|-------------|
-| F32  | 32-bit floating-point |
-| F64  | 64-bit floating-point |
-| Dec  | 128-bit decimal fixed-point (18 decimal places) |
-
-`Dec` is best for currency/base-10. `F32`/`F64` have precision loss with decimals.
-
-### Num, Int, Frac
-
-```roc
-abs : Num a -> Num a           # Any number
-bitwise_xor : Int a, Int a -> Int a  # Integers only
-cos : Frac a -> Frac a         # Fractions only
-```
-
-Number literals have type `Num *` (or `Frac *` with decimal point).
-
-### Number Literal Suffixes
-
-```roc
-1u8    # U8
-5dec   # Dec
-0xfe   # Hex (254)
-0b1000 # Binary (8)
-```
-
-Suffixes: `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `u128`, `i128`, `f32`, `f64`, `dec`
-
-### Default-Value Record Fields
-
-```roc
-table : { height : U64, width : U64, title ?? Str, description ?? Str } -> Table
-table = |{ height, width, title ?? "oak", description ?? "a wooden table" }| ...
-```
-
-`??` in types marks optional fields. Only accessible via destructuring.
-
-## Crashing
-
-Crashes: integer overflow, out of memory, `crash` keyword.
-
-```roc
-when Str.from_utf8(bytes) is
-    Ok(str) -> str
-    Err(_) -> crash "This should never happen!"
-
-# TODO marker
-crash "TODO handle the x <= y case"
-```
-
-Not for error handlingโ€”use `Result` instead.
-
-## Testing
-
-```roc
-pluralize = |singular, plural, count|
-    if count == 1 then "${Num.to_str(count)} ${singular}"
-    else "${Num.to_str(count)} ${plural}"
-
-expect pluralize("cactus", "cacti", 1) == "1 cactus"
-expect pluralize("cactus", "cacti", 2) == "2 cacti"
-```
-
-Run: `roc test`
-
-### Inline Expects
-
-```roc
-pluralize = |singular, plural, count|
-    if count == 1 then "${Num.to_str(count)} ${singular}"
-    else
-        expect count > 0
-        "${Num.to_str(count)} ${plural}"
-```
-
-- `roc build`: discards all expects
-- `roc dev`: runs inline expects during execution
-- `roc test`: runs top-level expects and triggered inline expects
-
-## Modules
-
-Types: `app` (application), `module`, `package`, `platform`, `hosted`
-
-### Builtin Modules (auto-imported)
-
-Str, Num, Bool, Result, List, Dict, Set, Decode, Encode, Hash, Box, Inspect
-
-### App Module Header
-
-```roc
-app [main!] { pf: platform "https://..." }
-
-import pf.Stdout
-import AdditionalModule
-import uuid.Generate as Uuid
-import pf.Stdout exposing [line!]
-```
-
-### Importing Files
-
-```roc
-import "some-file" as some_str : Str
-import "some-file" as some_bytes : List U8
-```
-
-## Effectful Functions
-
-Pure functions: `->`, effectful: `=>`
-
-```roc
-with_extension : Str -> Str           # Pure
-read_file! : Str => Str               # Effectful
-```
-
-Effectful functions can call pure or effectful. Pure can only call pure.
-`!` suffix is naming convention (compiler-enforced).
-
-```roc
-Stdout.line! : Str => Result {} [StdoutErr IOErr]
-Stdin.line! : {} => Result Str [EndOfFile, StdinErr IOErr]
-```
-
-### Reading Input
-
-```roc
-main! = |_args|
-    Stdout.line!("Type something:")?
-    input = Stdin.line!({})?
-    Stdout.line!("You entered: ${input}")
-```
-
-### Handling Failure
-
-```roc
-main! : List Arg => Result {} [Exit I32 Str]
-main! = |_args|
-    Result.map_err(my_function!({}), |err|
-        when err is
-            StdoutErr(_) -> Exit(1i32, "Error writing to stdout.")
-            StdinErr(_) -> Exit(2i32, "Error writing to stdin.")
-            EndOfFile -> Exit(3i32, "End of file reached.")
-    )
-```
-
-### Tagging Errors
-
-```roc
-main! = |_args|
-    Stdout.line!("Prompt") ? UnableToPrintPrompt
-    input = Stdin.line!({}) ? UnableToReadInput
-    Stdout.line!("You entered: ${input}") ? UnableToPrintInput
-    Ok({})
-```
-
-### Inspect.to_str
-
-```roc
-Inspect.to_str(any_value)  # String representation for debugging
-```
-
-### Early return
-
-```roc
-if this_is_a_bad_time then
-    return "Error message"
-else
-    continue_normally
-```
-
-## Advanced Concepts
-
-### Open vs Closed Records
-
-```roc
-# Closed: exact fields only
-full_name : { first_name : Str, last_name : Str } -> Str
-
-# Open: at least these fields (note the *)
-full_name : { first_name : Str, last_name : Str }* -> Str
-
-# Constrained: same type in and out
-add_https : { url : Str }a -> { url : Str }a
-```
-
-Inference:
-- Creating record โ†’ closed
-- Using as argument/destructuring โ†’ open
-- Record update โ†’ constrained
-
-### Type Alias with Variable
-
-```roc
-User a : { email : Str, first_name : Str, last_name : Str }a
-
-is_valid : User * -> Bool        # Open
-user_from_email : Str -> User {} # Closed
-capitalize : User a -> User a    # Constrained
-```
-
-### Open vs Closed Tag Unions
-
-```roc
-# Open: might have unknown tags (needs _ -> branch)
-example : [Foo Str, Bar Bool]* -> Bool
-example = |tag|
-    when tag is
-        Foo(str) -> Str.is_empty(str)
-        Bar(bool) -> bool
-        _ -> Bool.false
-
-# Closed: exactly these tags
-example : [Foo Str, Bar Bool] -> Bool
-example = |tag|
-    when tag is
-        Foo(str) -> Str.is_empty(str)
-        Bar(bool) -> bool
-```
-
-New tags are inferred as open unions and can accumulate through conditionals.
-
-### Constrained Tag Unions
-
-```roc
-example : [Foo Str, Bar Bool]a -> [Foo Str, Bar Bool]a
-example = |tag|
-    when tag is
-        Foo(str) -> Bar(Str.is_empty(str))
-        Bar(bool) -> Bar(Bool.false)
-        other -> other
-```
-
-### Record Builder
-
-```roc
-user_tab_matcher =
-    { combine_matchers <-
-        _: exact_segment("users"),  # Ignored field
-        user_id: u64_segment,
-        tab: any_segment,
-    }
-```
-
-Desugars to nested `combine_matchers` calls.
-
-### Reserved Keywords
-
-`as`, `crash`, `dbg`, `else`, `expect`, `expect-fx`, `if`, `import`, `is`, `return`, `then`, `try`, `when`
-
-### Operator Desugaring
-
-| Operator | Desugars To |
-|----------|-------------|
-| `a + b` | `Num.add(a, b)` |
-| `a - b` | `Num.sub(a, b)` |
-| `a * b` | `Num.mul(a, b)` |
-| `a / b` | `Num.div(a, b)` |
-| `a // b` | `Num.div_trunc(a, b)` |
-| `a ^ b` | `Num.pow(a, b)` |
-| `a % b` | `Num.rem(a, b)` |
-| `-a` | `Num.neg(a)` |
-| `a == b` | `Bool.is_eq(a, b)` |
-| `a != b` | `Bool.is_not_eq(a, b)` |
-| `a && b` | `Bool.and(a, b)` |
-| `a \|\| b` | `Bool.or(a, b)` |
-| `!a` | `Bool.not(a)` |
-| `a \|> f` | `f(a)` |

skills/writing-roc-lang/references/scripting.md ๐Ÿ”—

@@ -1,96 +0,0 @@
-# CLI Scripting with Roc
-
-Scripts run with `roc` or compile to standalone binaries via the basic-cli platform.
-
-**Platform version**: Examples use basic-cli 0.20.0. Check https://github.com/roc-lang/basic-cli/releases for latest.
-
-## Script structure
-
-```roc
-#!/usr/bin/env roc
-app [main!] { cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.20.0/X73hGh05nNTkDHU06FHC0YfFaQB1pimX7gncRcao5mU.tar.br" }
-
-import cli.Stdout
-
-main! = |_args|
-    Stdout.line!("Hello, World!")
-```
-
-Make executable: `chmod +x script.roc`, then run: `./script.roc`
-
-If `roc` not in PATH, use full path in shebang: `#!/home/user/.local/share/roc/current/roc`
-
-## Command-line arguments
-
-```roc
-#!/usr/bin/env roc
-app [main!] {
-    cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.20.0/X73hGh05nNTkDHU06FHC0YfFaQB1pimX7gncRcao5mU.tar.br",
-}
-
-import cli.Stdout
-import cli.Arg exposing [Arg]
-
-main! : List Arg => Result {} _
-main! = |raw_args|
-    args = List.map(raw_args, Arg.display)
-
-    # Index 0 is executable path, 1 is first real argument
-    when List.get(args, 1) is
-        Err(_) ->
-            Err(Exit(1, "Error: Expected one argument\n\tUsage: ./script.roc <input>"))
-
-        Ok(first_arg) ->
-            Stdout.line!("Received: ${first_arg}")
-```
-
-## Platform imports
-
-Common modules from `cli` platform:
-
-| Module | Purpose |
-|--------|---------|
-| `cli.Stdout` | Write to stdout |
-| `cli.Stdin` | Read from stdin |
-| `cli.File` | File operations |
-| `cli.Path` | Path handling |
-| `cli.Arg` | Command-line arguments |
-| `cli.Env` | Environment variables |
-| `cli.Dir` | Directory operations |
-
-## Reading stdin
-
-```roc
-import cli.Stdin
-import cli.Stdout
-
-main! = |_args|
-    input = Stdin.line!
-    Stdout.line!("You entered: ${input}")
-```
-
-## File operations
-
-```roc
-import cli.File
-import cli.Path
-import cli.Stdout
-
-main! = |_args|
-    path = Path.from_str("input.txt")
-    content = File.read_utf8!(path)?
-    Stdout.line!("File content: ${content}")
-```
-
-## When to use Roc scripts
-
-**Good for:**
-- Type-safe scripts catching errors at compile time
-- Functional programming enthusiasts
-- Long-lived scripts benefiting from stability
-- Learning functional programming
-
-**Avoid for:**
-- Production-critical code (Roc pre-1.0, breaking changes possible)
-- Quick throwaway scripts (compilation overhead)
-- When team doesn't know functional programming