Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

read_file

The prelude’s read_file, slated to be the first real definition: a .tr spec (prose, capability-style signature, fake-capability test, real-mode cram test), its .soil lowering, and its .lock entry. The canonical files live in examples/; these are included verbatim.

read_file.tr

---
name: read_file
---

# read_file

Reads an entire file into a UTF-8 string. Returns `Err` if the file does not
exist, cannot be read, or is not valid UTF-8. Never panics.

```soil-sig
read_file : (fs : Fs) -> (path : Path) -> io (Result Utf8 FsError)
```

```test found-and-missing
with fs = fake_fs {"config.toml": "port = 8080"}
(fs, "config.toml") => {"tag": "Ok", "value": "port = 8080"}
(fs, "missing.toml") => {"tag": "Err", "value": {"tag": "NotFound", "value": {"path": "missing.toml"}}}
```

One real-mode test against the actual filesystem:

```cram real-read
with file "config.toml" = "port = 8080"
$ trellis call read_file '"config.toml"'
{"tag": "Ok", "value": "port = 8080"}
```

read_file.soil

read_file : (fs : Fs) -> (path : Path) -> io (Result Utf8 FsError)
read_file fs path =
  match fs_read_bytes fs path with
  | Err e -> Err e
  | Ok bytes ->
    match utf8_decode bytes with
    | Ok text -> Ok text
    | Err _ -> Err (NotUtf8 { path = path })

read_file.lock

{
  "lock_format": 1,
  "name": "read_file",
  "kind": "function",
  "versions": { "trellis": "0.1", "soil": "0.1" },
  "spec": {
    "provenance": "human",
    "hashes": {
      "formal": "sha256:0be4d1c7",
      "test": "sha256:9a31e0f8",
      "prose": "sha256:5cc2071d"
    },
    "prose_state": "fresh",
    "blocks": [
      { "block": "soil-sig", "author": "human" },
      { "block": "test found-and-missing", "author": "human" },
      { "block": "cram real-read", "author": "human" }
    ],
    "pinned": true,
    "escape_hatches": []
  },
  "lowering": {
    "soil_hash": "sha256:ce8842a0",
    "provenance": "human-verified",
    "provider": "claude-code",
    "model": "claude-opus-4-7",
    "private_helpers": [],
    "calls": [
      { "name": "fs_read_bytes", "hash": "sha256:44f7b2e9" },
      { "name": "utf8_decode", "hash": "sha256:d10a93c5" }
    ]
  },
  "checks": {
    "types": "ok",
    "refinements": "none",
    "demoted": []
  },
  "tests": [
    { "name": "found-and-missing#1", "tier": "expect", "mode": "sandboxed", "origin": "spec", "result": "pass" },
    { "name": "found-and-missing#2", "tier": "expect", "mode": "sandboxed", "origin": "spec", "result": "pass" },
    { "name": "real-read#1", "tier": "cram", "mode": "real", "origin": "spec", "result": "pass" }
  ],
  "oracles": [],
  "accepted": true
}