functionalscript 0.45.0 → 0.46.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (296) hide show
  1. package/README.md +5 -3
  2. package/fjs/asn.1/module.f.mjs +8 -1
  3. package/fjs/asn.1/proof.f.d.mts +10 -0
  4. package/fjs/asn.1/proof.f.mjs +16 -0
  5. package/fjs/basen/base128/module.f.mjs +22 -5
  6. package/fjs/bnf/data/module.f.d.mts +32 -6
  7. package/fjs/bnf/data/module.f.mjs +112 -7
  8. package/fjs/bnf/data/proof.f.d.mts +2 -0
  9. package/fjs/bnf/data/proof.f.mjs +74 -3
  10. package/fjs/bnf/data/types.d.ts +20 -2
  11. package/fjs/bnf/descent/module.f.d.mts +28 -14
  12. package/fjs/bnf/descent/module.f.mjs +122 -77
  13. package/fjs/bnf/descent/proof.f.d.mts +2 -0
  14. package/fjs/bnf/descent/proof.f.mjs +117 -31
  15. package/fjs/bnf/descent/types.d.ts +12 -14
  16. package/fjs/bnf/ll1/module.f.d.mts +64 -22
  17. package/fjs/bnf/ll1/module.f.mjs +214 -154
  18. package/fjs/bnf/ll1/proof.f.d.mts +15 -2
  19. package/fjs/bnf/ll1/proof.f.mjs +323 -149
  20. package/fjs/bnf/ll1/types.d.ts +16 -24
  21. package/fjs/bnf/matcher/module.f.d.mts +66 -0
  22. package/fjs/bnf/matcher/module.f.mjs +81 -0
  23. package/fjs/bnf/matcher/proof.f.d.mts +10 -0
  24. package/fjs/bnf/matcher/proof.f.mjs +79 -0
  25. package/fjs/bnf/matcher/types.d.ts +54 -0
  26. package/fjs/bnf/testlib.f.d.mts +31 -0
  27. package/fjs/bnf/testlib.f.mjs +80 -0
  28. package/fjs/cas/cli/module.f.d.mts +1 -1
  29. package/fjs/cas/cli/module.f.mjs +14 -20
  30. package/fjs/cas/cli/proof.f.d.mts +1 -3
  31. package/fjs/cas/cli/proof.f.mjs +44 -33
  32. package/fjs/cas/evo/module.f.d.mts +64 -18
  33. package/fjs/cas/evo/module.f.mjs +148 -70
  34. package/fjs/cas/evo/proof.f.d.mts +10 -1
  35. package/fjs/cas/evo/proof.f.mjs +305 -223
  36. package/fjs/cas/evo/types.d.ts +45 -9
  37. package/fjs/cas/module.f.d.mts +18 -32
  38. package/fjs/cas/module.f.mjs +129 -128
  39. package/fjs/cas/proof.f.d.mts +11 -8
  40. package/fjs/cas/proof.f.mjs +259 -147
  41. package/fjs/cas/types.d.ts +24 -10
  42. package/fjs/ci/config/module.f.d.mts +2 -2
  43. package/fjs/ci/config/module.f.mjs +2 -2
  44. package/fjs/ci/module.f.d.mts +5 -5
  45. package/fjs/ci/module.f.mjs +8 -7
  46. package/fjs/ci/nix/module.f.d.mts +7 -5
  47. package/fjs/ci/nix/module.f.mjs +13 -12
  48. package/fjs/ci/nix/proof.f.mjs +2 -2
  49. package/fjs/ci/proof.f.mjs +9 -5
  50. package/fjs/cli/module.f.d.mts +4 -6
  51. package/fjs/cli/module.f.mjs +4 -8
  52. package/fjs/cli/proof.f.mjs +17 -16
  53. package/fjs/cli/types.d.ts +2 -3
  54. package/fjs/common/monoid/types.d.ts +1 -1
  55. package/fjs/crypto/hmac/module.f.mjs +2 -2
  56. package/fjs/crypto/sha2/module.f.mjs +3 -1
  57. package/fjs/crypto/sha2/proof.f.d.mts +1 -0
  58. package/fjs/crypto/sha2/proof.f.mjs +24 -0
  59. package/fjs/crypto/sha2/types.d.ts +11 -0
  60. package/fjs/crypto/sign/module.f.mjs +2 -2
  61. package/fjs/dev/module.f.d.mts +13 -4
  62. package/fjs/dev/module.f.mjs +56 -27
  63. package/fjs/dev/update/module.f.d.mts +9 -4
  64. package/fjs/dev/update/module.f.mjs +14 -10
  65. package/fjs/dev/update/proof.f.d.mts +1 -3
  66. package/fjs/dev/update/proof.f.mjs +10 -5
  67. package/fjs/djs/module.f.d.mts +13 -5
  68. package/fjs/djs/module.f.mjs +31 -16
  69. package/fjs/djs/parser/module.f.d.mts +13 -3
  70. package/fjs/djs/parser/module.f.mjs +117 -16
  71. package/fjs/djs/parser/proof.f.d.mts +5 -1
  72. package/fjs/djs/parser/proof.f.mjs +274 -12
  73. package/fjs/djs/parser/types.d.ts +7 -1
  74. package/fjs/djs/proof.f.d.mts +18 -2
  75. package/fjs/djs/proof.f.mjs +187 -12
  76. package/fjs/djs/serializer/module.f.d.mts +25 -8
  77. package/fjs/djs/serializer/module.f.mjs +61 -15
  78. package/fjs/djs/serializer/proof.f.d.mts +5 -0
  79. package/fjs/djs/serializer/proof.f.mjs +23 -1
  80. package/fjs/djs/tokenizer/module.f.d.mts +17 -5
  81. package/fjs/djs/tokenizer/module.f.mjs +99 -60
  82. package/fjs/djs/tokenizer/proof.f.d.mts +1 -1
  83. package/fjs/djs/tokenizer/proof.f.mjs +74 -67
  84. package/fjs/djs/transpiler/module.f.d.mts +12 -7
  85. package/fjs/djs/transpiler/module.f.mjs +82 -56
  86. package/fjs/djs/transpiler/types.d.ts +7 -3
  87. package/fjs/djs/types.d.ts +7 -1
  88. package/fjs/effects/list/module.f.d.mts +14 -11
  89. package/fjs/effects/list/module.f.mjs +13 -11
  90. package/fjs/effects/list/types.d.ts +27 -7
  91. package/fjs/effects/memory/module.f.d.mts +2 -1
  92. package/fjs/effects/memory/module.f.mjs +3 -4
  93. package/fjs/effects/memory/proof.f.mjs +13 -7
  94. package/fjs/effects/memory/types.d.ts +4 -3
  95. package/fjs/effects/mock/module.f.d.mts +20 -4
  96. package/fjs/effects/mock/module.f.mjs +37 -5
  97. package/fjs/effects/mock/types.d.ts +10 -1
  98. package/fjs/effects/module.d.mts +4 -2
  99. package/fjs/effects/module.f.d.mts +466 -280
  100. package/fjs/effects/module.f.mjs +537 -299
  101. package/fjs/effects/module.mjs +2 -1
  102. package/fjs/effects/node/memory/module.d.mts +4 -2
  103. package/fjs/effects/node/memory/module.mjs +6 -3
  104. package/fjs/effects/node/memory/proof.mjs +10 -4
  105. package/fjs/effects/node/module.d.mts +4 -3
  106. package/fjs/effects/node/module.f.d.mts +168 -33
  107. package/fjs/effects/node/module.f.mjs +256 -52
  108. package/fjs/effects/node/module.mjs +57 -34
  109. package/fjs/effects/node/proof.f.d.mts +28 -2
  110. package/fjs/effects/node/proof.f.mjs +161 -42
  111. package/fjs/effects/node/types.d.ts +106 -18
  112. package/fjs/effects/node/virtual/module.f.d.mts +18 -4
  113. package/fjs/effects/node/virtual/module.f.mjs +110 -68
  114. package/fjs/effects/node/virtual/proof.f.d.mts +28 -2
  115. package/fjs/effects/node/virtual/proof.f.mjs +190 -9
  116. package/fjs/effects/proof.f.d.mts +69 -37
  117. package/fjs/effects/proof.f.mjs +410 -130
  118. package/fjs/effects/types.d.ts +161 -33
  119. package/fjs/emergent_testing/module.f.d.mts +19 -12
  120. package/fjs/emergent_testing/module.f.mjs +93 -33
  121. package/fjs/emergent_testing/proof.f.d.mts +21 -7
  122. package/fjs/emergent_testing/proof.f.mjs +166 -32
  123. package/fjs/emergent_testing/types.d.ts +22 -4
  124. package/fjs/fsm/module.f.d.mts +14 -4
  125. package/fjs/fsm/module.f.mjs +54 -37
  126. package/fjs/fsm/proof.f.d.mts +2 -0
  127. package/fjs/fsm/proof.f.mjs +83 -114
  128. package/fjs/js/keywords/module.f.d.mts +52 -0
  129. package/fjs/js/keywords/module.f.mjs +72 -0
  130. package/fjs/js/keywords/proof.f.d.mts +3 -0
  131. package/fjs/js/keywords/proof.f.mjs +13 -0
  132. package/fjs/js/tokenizer/module.f.d.mts +26 -6
  133. package/fjs/js/tokenizer/module.f.mjs +145 -159
  134. package/fjs/js/tokenizer/proof.f.d.mts +1 -0
  135. package/fjs/js/tokenizer/proof.f.mjs +54 -24
  136. package/fjs/js/tokenizer/types.d.ts +33 -24
  137. package/fjs/mcp/cas/module.f.d.mts +1 -6
  138. package/fjs/mcp/cas/module.f.mjs +55 -51
  139. package/fjs/mcp/cas/proof.f.d.mts +15 -0
  140. package/fjs/mcp/cas/proof.f.mjs +174 -0
  141. package/fjs/mcp/evo/module.f.d.mts +19 -10
  142. package/fjs/mcp/evo/module.f.mjs +48 -27
  143. package/fjs/mcp/evo/proof.f.d.mts +6 -1
  144. package/fjs/mcp/evo/proof.f.mjs +115 -31
  145. package/fjs/mcp/module.f.d.mts +4 -4
  146. package/fjs/mcp/module.f.mjs +6 -6
  147. package/fjs/mcp/proof.f.d.mts +5 -3
  148. package/fjs/mcp/proof.f.mjs +112 -46
  149. package/fjs/media/html/module.f.mjs +1 -1
  150. package/fjs/media/json/extended/module.f.d.mts +82 -0
  151. package/fjs/media/json/extended/module.f.mjs +153 -0
  152. package/fjs/media/json/extended/proof.f.d.mts +42 -0
  153. package/fjs/media/json/extended/proof.f.mjs +127 -0
  154. package/fjs/media/json/extended/types.d.ts +23 -0
  155. package/fjs/media/json/module.f.d.mts +8 -2
  156. package/fjs/media/json/module.f.mjs +43 -41
  157. package/fjs/media/json/number/module.f.d.mts +59 -0
  158. package/fjs/media/json/number/module.f.mjs +136 -0
  159. package/fjs/media/json/number/proof.f.d.mts +24 -0
  160. package/fjs/media/json/number/proof.f.mjs +86 -0
  161. package/fjs/media/json/number/types.d.ts +28 -0
  162. package/fjs/media/json/parser/module.f.d.mts +25 -13
  163. package/fjs/media/json/parser/module.f.mjs +114 -70
  164. package/fjs/media/json/parser/proof.f.d.mts +5 -0
  165. package/fjs/media/json/parser/proof.f.mjs +31 -1
  166. package/fjs/media/json/parser/types.d.ts +33 -14
  167. package/fjs/media/json/rtti/module.f.d.mts +1 -1
  168. package/fjs/media/json/rtti/module.f.mjs +1 -1
  169. package/fjs/media/json/rtti/proof.f.mjs +9 -9
  170. package/fjs/media/json/schema/module.f.mjs +3 -13
  171. package/fjs/media/json/schema/proof.f.d.mts +0 -1
  172. package/fjs/media/json/schema/proof.f.mjs +1 -2
  173. package/fjs/media/json/serializer/module.f.d.mts +32 -1
  174. package/fjs/media/json/serializer/module.f.mjs +64 -2
  175. package/fjs/media/json/tokenizer/module.f.mjs +7 -3
  176. package/fjs/media/json/tokenizer/proof.f.d.mts +6 -0
  177. package/fjs/media/json/tokenizer/proof.f.mjs +62 -21
  178. package/fjs/media/json/types.d.ts +36 -10
  179. package/fjs/media/lock/module.f.d.mts +100 -0
  180. package/fjs/media/lock/module.f.mjs +125 -0
  181. package/fjs/media/lock/proof.f.d.mts +33 -0
  182. package/fjs/media/lock/proof.f.mjs +196 -0
  183. package/fjs/media/lock/types.d.ts +15 -0
  184. package/fjs/media/module.f.d.mts +6 -5
  185. package/fjs/media/module.f.mjs +8 -7
  186. package/fjs/media/note/module.f.d.mts +121 -0
  187. package/fjs/media/note/module.f.mjs +131 -0
  188. package/fjs/media/note/proof.f.d.mts +29 -0
  189. package/fjs/media/note/proof.f.mjs +150 -0
  190. package/fjs/media/note/types.d.ts +10 -0
  191. package/fjs/media/proof.f.d.mts +4 -1
  192. package/fjs/media/proof.f.mjs +40 -21
  193. package/fjs/media/revision/module.f.d.mts +78 -7
  194. package/fjs/media/revision/module.f.mjs +119 -12
  195. package/fjs/media/revision/proof.f.d.mts +10 -0
  196. package/fjs/media/revision/proof.f.mjs +88 -0
  197. package/fjs/media/revision/types.d.ts +34 -5
  198. package/fjs/media/type/module.f.d.mts +33 -15
  199. package/fjs/media/type/module.f.mjs +35 -29
  200. package/fjs/media/type/proof.f.d.mts +2 -1
  201. package/fjs/media/type/proof.f.mjs +30 -10
  202. package/fjs/module.f.mjs +29 -8
  203. package/fjs/nanvm/proof.f.mjs +3 -3
  204. package/fjs/nanvm/rust/module.f.mjs +1 -1
  205. package/fjs/nanvm/update/module.f.d.mts +4 -4
  206. package/fjs/nanvm/update/module.f.mjs +8 -9
  207. package/fjs/nanvm/update/proof.f.mjs +4 -3
  208. package/fjs/proof.f.d.mts +3 -3
  209. package/fjs/proof.f.mjs +36 -10
  210. package/fjs/protocol/json_rpc/module.f.d.mts +2 -2
  211. package/fjs/protocol/json_rpc/module.f.mjs +3 -3
  212. package/fjs/protocol/json_rpc/proof.f.mjs +4 -4
  213. package/fjs/protocol/mcp/module.f.d.mts +10 -13
  214. package/fjs/protocol/mcp/module.f.mjs +74 -58
  215. package/fjs/protocol/mcp/proof.f.d.mts +13 -4
  216. package/fjs/protocol/mcp/proof.f.mjs +193 -61
  217. package/fjs/protocol/mcp/stdio/module.f.d.mts +15 -7
  218. package/fjs/protocol/mcp/stdio/module.f.mjs +38 -25
  219. package/fjs/protocol/mcp/stdio/proof.f.d.mts +4 -2
  220. package/fjs/protocol/mcp/stdio/proof.f.mjs +45 -12
  221. package/fjs/protocol/mcp/stdio/types.d.ts +1 -1
  222. package/fjs/protocol/mcp/types.d.ts +17 -6
  223. package/fjs/sul/id/module.f.d.mts +0 -1
  224. package/fjs/sul/id/module.f.mjs +2 -3
  225. package/fjs/sul/level/hash/module.f.mjs +2 -1
  226. package/fjs/sul/level/hash/proof.f.mjs +2 -2
  227. package/fjs/sul/module.f.mjs +18 -13
  228. package/fjs/text/code_point/module.f.d.mts +8 -0
  229. package/fjs/text/code_point/module.f.mjs +8 -1
  230. package/fjs/text/code_point/proof.f.d.mts +1 -0
  231. package/fjs/text/code_point/proof.f.mjs +11 -0
  232. package/fjs/text/sgr/module.f.d.mts +4 -6
  233. package/fjs/text/sgr/module.f.mjs +6 -7
  234. package/fjs/text/utf16/module.f.mjs +7 -2
  235. package/fjs/text/utf16/proof.f.mjs +3 -3
  236. package/fjs/text/utf8/module.f.mjs +4 -2
  237. package/fjs/types/array/module.f.mjs +14 -2
  238. package/fjs/types/bit_vec/module.f.d.mts +0 -2
  239. package/fjs/types/bit_vec/module.f.mjs +46 -32
  240. package/fjs/types/bit_vec/proof.f.mjs +2 -2
  241. package/fjs/types/btree/remove/module.f.mjs +1 -1
  242. package/fjs/types/btree/set/module.f.mjs +9 -11
  243. package/fjs/types/btree/set/proof.f.mjs +12 -0
  244. package/fjs/types/byte_set/module.f.d.mts +11 -4
  245. package/fjs/types/byte_set/module.f.mjs +14 -6
  246. package/fjs/types/byte_set/proof.f.mjs +7 -7
  247. package/fjs/types/function/compare/module.f.mjs +10 -3
  248. package/fjs/types/list/module.f.d.mts +1 -1
  249. package/fjs/types/list/module.f.mjs +1 -1
  250. package/fjs/types/nullable/module.f.d.mts +18 -4
  251. package/fjs/types/nullable/module.f.mjs +21 -4
  252. package/fjs/types/nullable/proof.f.d.mts +4 -0
  253. package/fjs/types/nullable/proof.f.mjs +15 -0
  254. package/fjs/types/object/module.f.d.mts +12 -2
  255. package/fjs/types/object/module.f.mjs +11 -1
  256. package/fjs/types/patricia_trie/module.f.mjs +26 -11
  257. package/fjs/types/result/module.f.d.mts +3 -3
  258. package/fjs/types/result/module.f.mjs +3 -3
  259. package/fjs/types/rtti/common/module.f.d.mts +25 -28
  260. package/fjs/types/rtti/common/module.f.mjs +36 -32
  261. package/fjs/types/rtti/common/proof.f.mjs +5 -5
  262. package/fjs/types/rtti/data/module.f.d.mts +14 -0
  263. package/fjs/types/rtti/data/module.f.mjs +25 -2
  264. package/fjs/types/rtti/data/proof.f.d.mts +1 -0
  265. package/fjs/types/rtti/data/proof.f.mjs +25 -2
  266. package/fjs/types/rtti/parse/module.f.d.mts +24 -14
  267. package/fjs/types/rtti/parse/module.f.mjs +37 -28
  268. package/fjs/types/rtti/parse/proof.f.d.mts +3 -2
  269. package/fjs/types/rtti/parse/proof.f.mjs +33 -14
  270. package/fjs/types/rtti/proof.f.mjs +3 -1
  271. package/fjs/types/rtti/ts/module.f.mjs +13 -17
  272. package/fjs/types/rtti/ts/types.d.ts +14 -1
  273. package/fjs/types/rtti/validate/module.f.d.mts +81 -19
  274. package/fjs/types/rtti/validate/module.f.mjs +107 -61
  275. package/fjs/types/rtti/validate/proof.f.d.mts +13 -10
  276. package/fjs/types/rtti/validate/proof.f.mjs +186 -197
  277. package/fjs/types/sorted_set/module.f.d.mts +18 -0
  278. package/fjs/types/sorted_set/module.f.mjs +22 -0
  279. package/fjs/types/sorted_set/proof.f.d.mts +1 -0
  280. package/fjs/types/sorted_set/proof.f.mjs +16 -1
  281. package/fjs/types/uint8array/module.f.d.mts +1 -1
  282. package/fjs/types/uint8array/module.f.mjs +1 -1
  283. package/fjs/website/module.f.d.mts +3 -3
  284. package/fjs/website/module.f.mjs +4 -7
  285. package/fjs/website/proof.f.mjs +2 -1
  286. package/package.json +2 -2
  287. package/fjs/dev/package_json/module.f.d.mts +0 -39
  288. package/fjs/dev/package_json/module.f.mjs +0 -40
  289. package/fjs/dev/package_json/proof.f.d.mts +0 -6
  290. package/fjs/dev/package_json/proof.f.mjs +0 -32
  291. package/fjs/effects/eff/module.f.d.mts +0 -20
  292. package/fjs/effects/eff/module.f.mjs +0 -70
  293. package/fjs/effects/eff/proof.f.d.mts +0 -15
  294. package/fjs/effects/eff/proof.f.mjs +0 -69
  295. package/fjs/effects/eff/types.d.ts +0 -71
  296. package/fjs/types/rtti/validate/types.d.ts +0 -6
@@ -1,23 +1,69 @@
1
1
  /**
2
- * Core effect type constructors and combinators.
3
- *
4
- * An `Effect<O, T>` **is** the raw value — a `Pure` thunk (`() => T`) or a `Do`
5
- * node (`{ command, payload, continuation }`). It is plain data with no methods.
6
- * Composition is provided externally by {@link step}. The optional
7
- * method-chaining wrapper lives in `fjs/effects/eff/module.f.mjs`.
8
- *
9
- * **Three functions discriminate `Pure` from `Do`** — {@link step},
10
- * {@link match}, and {@link runPure} — plus the node proof in
11
- * `fjs/effects/proof.f.mjs` that pins the representation on purpose. Everything
12
- * else, interpreters included, goes through `match` or `runPure`. The count is
13
- * the point: a `typeof e === 'function'` check appearing in a fifth place is a
14
- * review flag, because the representation is only cheap to change while its
15
- * readers stay enumerable.
16
- *
17
- * A `decode` function (`(e: Effect<O, T>) => Decoded<O, T>`) once funnelled all
18
- * of that through a single `{ done, result }` / `{ done, command, payload,
2
+ * The effect system: the representation, its interpreters, and the combinators
3
+ * that compose it.
4
+ *
5
+ * An `Effect<O, T, E>` **is** the raw value a `Pure` thunk
6
+ * (`() => Result<T, E>`) or a `Do` node (`{ command, payload, continuation }`).
7
+ * It is plain data with no methods; see [`./types.ts`](./types.ts) for the
8
+ * type-level API and [`./README.md`](./README.md) for why the error channel is
9
+ * part of it.
10
+ *
11
+ * **The three branch-aware operations are the whole composition vocabulary:**
12
+ *
13
+ * - {@link step} continue on `ok`, propagate the `error`. The normal path.
14
+ * - {@link catchStep} continue on `error`, preserve the `ok`. The error path.
15
+ * - {@link resultStep} — continue with the complete `Result`. Both paths.
16
+ *
17
+ * Around them: {@link pure} and the two lifts {@link pureOk} / {@link pureError}
18
+ * that enter the layer, the projections {@link mapStep} and
19
+ * {@link resultMapStep} that end a chain, {@link history} /
20
+ * {@link historyStep} for a chain whose later links read earlier values, and
21
+ * {@link foldStep} / {@link forEachStep} for iteration. The operation
22
+ * constructor is {@link do_}, and the eliminators are {@link match},
23
+ * {@link partialMatch} and {@link runPure}.
24
+ *
25
+ * **The error channel is unioned, not unified**, following `okThen`
26
+ * (`fjs/types/result/module.f.mjs`), the pure sibling of this bind: neither
27
+ * side is pre-widened, and a branch that is passed through stays the very tuple
28
+ * it arrived as rather than being rebuilt to retag it into a wider type.
29
+ * {@link step} unions the error channel and replaces the success type;
30
+ * {@link catchStep} mirrors it, unioning the success channel and replacing the
31
+ * error type.
32
+ *
33
+ * Recovery therefore never needs `try`/`catch` — which FunctionalScript does
34
+ * not offer, and whose `throw` stays reserved for panics. Escalating an error
35
+ * to a panic is a decision the program makes explicitly, by `unwrap`ping what
36
+ * {@link resultStep} hands it.
37
+ *
38
+ * **This was two modules, and briefly two of each combinator.** A `./io/`
39
+ * directory held the branch-aware set while this file held a `Result`-blind
40
+ * `step`, `mapStep`, `history`, `historyStep`, `foldStep` and `forEachStep`
41
+ * beside the representation. Those were traps rather than a layer: an operation
42
+ * must return a `Result`, so every effect carries one, and a `step` that ran
43
+ * its continuation whether or not the previous effect failed described no case
44
+ * worth having. They are gone — {@link resultStep} *is* that former general
45
+ * `step`, at the type that says what its continuation receives — and with the
46
+ * name collision went the only reason for two modules. The directory was called
47
+ * `io` because it was the fallible layer over a raw one; nothing in it was ever
48
+ * specific to IO.
49
+ *
50
+ * **Three functions discriminate `Pure` from `Do`** — {@link resultStep},
51
+ * {@link _matchWith} and {@link runPure} — plus the node proof in
52
+ * `./proof.f.mjs` that pins the representation on purpose. Everything else,
53
+ * interpreters included, goes through `match`, {@link partialMatch}, or
54
+ * `runPure`. The count is the point: a `typeof e === 'function'` check
55
+ * appearing in a fourth place is a review flag, because the representation is
56
+ * only cheap to change while its readers stay enumerable. It used to be a
57
+ * cross-module claim, with one of the three on the far side of the boundary.
58
+ *
59
+ * `match` and `partialMatch` are two entry points, not two discriminators:
60
+ * they differ only in what a missing handler means and share `_matchWith` for
61
+ * the shape test, so adding the partial variant left the count where it was.
62
+ *
63
+ * A `decode` function (`(e: Effect<O, T, E>) => Decoded<O, T, E>`) once funnelled
64
+ * all of that through a single `{ done, result }` / `{ done, command, payload,
19
65
  * continuation }` record, so that exactly one function held the shape test. It
20
- * has been removed. `Effect` is a function type unioned with an object type, so
66
+ * has been removed. An effect is a function type unioned with an object type, so
21
67
  * `typeof e === 'function'` is already a complete discriminant: `decode` bought
22
68
  * no narrowing, it re-encoded that narrowing as a `done` flag to be re-narrowed
23
69
  * one indirection later, and its `Decoded` record was declared in terms of the
@@ -26,327 +72,467 @@
26
72
  * the same nothing — and with {@link Do} now carrying named fields there is not
27
73
  * even a positional layout left for it to insulate anyone from.
28
74
  *
29
- * Effect helpers come in two shapes. **Step adapters** return a continuation
30
- * `(t: T) => Effect<Q, R>` meant to be passed into a step see {@link okStep}.
31
- * **Step variants** take the effect itself first, like {@link step} — see
32
- * {@link historyStep}. {@link mapStep} is the variant for the end of a chain:
33
- * a pure projection over an effect's result, which is a `step` that continues
34
- * with no further effect.
35
- *
36
- * **Do not nest steps.** Bind each intermediate effect to its own name, so a
37
- * sequence reads top-to-bottom in evaluation order:
38
- *
39
- * ```js
40
- * // avoid — reads inside-out, and gains a level of indentation per link
41
- * step(a, x => step(f(x), y => step(g(y), z => h(z))))
42
- *
43
- * // prefer — flat, one name per link
44
- * const x0 = step(a, f)
45
- * const x1 = step(x0, g)
46
- * return step(x1, h)
47
- * ```
48
- *
49
- * **A step call that does not fit one line breaks after `(`, one argument per
50
- * line.** This holds for every step variant — {@link step}, {@link mapStep},
51
- * {@link historyStep}, {@link foldStep}, {@link forEachStep} — and it is the
52
- * same rule as taking the effect first, written out at the call site. A step
53
- * variant is this module's
54
- * `do` notation: the arguments are a statement list in execution order, so each
55
- * one gets a line and the sequence reads down the page. Packing the leading
56
- * effect onto the `(` line and wrapping the rest beneath it hides which of them
57
- * runs first. The closing `)` may sit on its own line or trail the last
58
- * argument:
59
- *
60
- * ```js
61
- * return step(
62
- * collectRead(cas.read(hash)),
63
- * ([tag, value]) => pure(tag === 'error' ? null : decodeRevisionVec(value)))
64
- * ```
65
- *
66
- * When a later link needs a value from an earlier one, that is not a reason to
67
- * nest: a nested continuation only reaches back because it closes over the
68
- * enclosing scope. {@link historyStep} carries the value forward instead, so
69
- * the chain stays flat:
70
- *
71
- * ```js
72
- * // avoid — nested only so `h` can still see `x`
73
- * step(a, x => step(f(x), y => h(x, y)))
74
- *
75
- * // prefer — the history tuple carries `x` forward alongside `y`
76
- * const x0 = historyStep(history(a), f)
77
- * return step(x0, ([y, x]) => h(x, y))
78
- * ```
79
- *
80
- * Nesting is often forced by nothing more than a local declared inside a
81
- * continuation that does not depend on it. Hoist such locals above the chain
82
- * and the nesting usually dissolves on its own.
83
- *
84
- * That advice is for code *using* this module, and the combinators defined
85
- * here are what make it followable. The nesting has to exist somewhere: a name
86
- * cannot be bound to an effect that has not been produced yet, so `f(param)`
87
- * cannot become a `const` until `e` resolves. {@link step} recurses into
88
- * itself inside the continuation it rebuilds, {@link foldStep} composes one
89
- * step per item, and {@link historyStep} runs `f` inside `e`'s continuation.
90
- * Each writes that nesting down **once**, in one line, so that no caller ever
91
- * writes it again — that is what a combinator here is *for*. Without
92
- * {@link historyStep} the flat form would be unavailable the moment a later
93
- * link needed an earlier link's value.
94
- *
95
- * See `./types.ts` for the type-level API.
75
+ * **The composition rules:** bind each link in a sequence to its own name at one
76
+ * level, do not nest steps, and break a call that does not fit one line after
77
+ * `(` with one argument per line.
96
78
  *
97
79
  * @module
98
80
  *
99
81
  * @import { List } from '../types/list/types.ts'
82
+ * @import { Fold } from '../types/function/operator/types.ts'
100
83
  * @import { Option } from '../types/option/types.ts'
101
84
  * @import { Result } from '../types/result/types.ts'
102
- * @import { Fold } from '../types/function/operator/types.ts'
103
- * @import { Cont, Do, Effect, F, History, MatchResult, Operation, OperationMap, Param, Pr, Pure, Return, ToAsyncOperationMap } from './types.ts'
85
+ * @import { Commands, Effect, ErrOf, Func, MatchResult, NotImplemented, OkOf, Operation, OperationMap, PartialOperationMap } from './types.ts'
104
86
  */
105
87
  import type { List } from '../types/list/types.ts';
106
88
  import type { Option } from '../types/option/types.ts';
107
89
  import type { Result } from '../types/result/types.ts';
108
- import type { Effect, History, MatchResult, Operation, OperationMap, Param, Return } from './types.ts';
109
- /** @type {<T>(v: T) => Effect<never, T>} */
110
- export declare const pure: <T>(v: T) => Effect<never, T>;
90
+ import type { Commands, Effect, ErrOf, Func, MatchResult, NotImplemented, OkOf, Operation, OperationMap, PartialOperationMap } from './types.ts';
91
+ /**
92
+ * Lifts an already-computed {@link Result} into an effect that performs no
93
+ * command.
94
+ *
95
+ * It takes the `Result` rather than a bare value because that is what a `Pure`
96
+ * holds: the two channels are the representation's, so a constructor that took
97
+ * only a success would be `pureOk`, which is exactly what
98
+ * [`./module.f.mjs`](./module.f.mjs) exports alongside `pureError`. Reach
99
+ * for those; this one is for the `Result` you already have in your hand — a
100
+ * branch passing an incoming error through unchanged, or a runner's answer.
101
+ *
102
+ * **Both channels are read off the argument**, via {@link OkOf} / {@link ErrOf}
103
+ * rather than by matching `Result<T, E>` directly. Inference against the union
104
+ * cannot tell which half a one-sided argument belongs to — `pure(ok(v))` would
105
+ * infer the error channel as `T` as readily as `never` — so the halves are
106
+ * projected out of the concrete type instead. That is what makes `pureOk` land
107
+ * on `Effect<never, T, never>` and `pureError` on `Effect<never, never, E>`.
108
+ *
109
+ * @type {<R extends Result<unknown, unknown>>(r: R) => Effect<never, OkOf<R>, ErrOf<R>>}
110
+ */
111
+ export declare const pure: <R extends Result<unknown, unknown>>(r: R) => Effect<never, OkOf<R>, ErrOf<R>>;
112
+ /**
113
+ * @type {<O extends Operation>(command: O[0]) => Func<O>}
114
+ */
115
+ export declare const do_: <O extends Operation>(command: O[0]) => Func<O>;
111
116
  /**
112
- * Composes effects: run `e`, then continue with `f` applied to its result.
113
- * The data-first primitive raw `Effect` in, raw `Effect` out. Chains as
114
- * `step(step(e, f), g)`.
117
+ * Runs an effect that reaches its result without performing a command: `[r]`
118
+ * for a {@link Pure}, empty for a {@link Do}. Forces the thunk in the `Pure`
119
+ * case, which {@link Pure}'s contract makes free of consequence.
115
120
  *
116
- * **`step` is not lazy.** It reads `e`'s shape immediately, so a `Pure` head is
117
- * forced and `f` is called right there: `step(pure(v), f)` *is* `f(v)`,
118
- * evaluated where the composition is written rather than where the effect is
119
- * run. Only the `Do` case defers — the continuation rebuilt around `f` runs
120
- * when a runner reaches that node.
121
+ * The eliminator for callers that expect no operations at all the other side
122
+ * of {@link match}, which is for callers that intend to perform them.
121
123
  *
122
- * That is sound rather than an oversight, and it is sound only because of
123
- * {@link Pure}'s contract: a `Pure` holds a value that has already been
124
- * computed, so forcing it early observes nothing, repeats nothing, and can
125
- * throw nothing. `step` never performs a `Do` node, which is where anything
126
- * real lives. Break the contracthide work behind the thunk and merely
127
- * composing a chain starts running the program.
124
+ * **The result is tagged on purpose**, and the tag is not the `Result`'s. An
125
+ * `Option` distinguishes "reached a value" from "stopped at a command";
126
+ * the `Result` inside it distinguishes success from failure. Collapsing them
127
+ * would lose the case this exists to rule out an effect that unexpectedly
128
+ * stopped at a `Do` nodeso `[r]` is a pure result and `[]` is a `Do`.
128
129
  *
129
- * A composition cannot be suspended, and no combinator can fix that:
130
- * `defer: (() => Effect<O, T>) => Effect<O, T>` cannot be written here, because
131
- * the `Pure` / `Do` tag must be known before anything runs and the union has no
132
- * third case meaning "not yet decided". That is inherent to the representation,
133
- * not a gap in this module's API. A caller that needs to name a composition
134
- * without performing it yet has to keep the ingredients and defer the `step`
135
- * itself — `Eff` does exactly this, holding its history tuple as a thunk (`h`)
136
- * precisely because composing it eagerly is the one thing it cannot take back.
130
+ * `O` stays generic rather than narrowing to `Effect<never, T, E>`. An effect is
131
+ * covariant in `O`, so `Effect<never, T, E>` is assignable to `Effect<O, T, E>`
132
+ * and not the reverse a continuation's result is always the wider type and
133
+ * would be rejected. `Do<never, T, E>` is uninhabited besides, which would make
134
+ * the empty case unreachable without a cast.
137
135
  *
138
- * @type {<O extends Operation, T, Q extends Operation, R>(e: Effect<O, T>, f: (t: T) => Effect<Q, R>) => Effect<O | Q, R>}
136
+ * @type {<O extends Operation, T, E>(e: Effect<O, T, E>) => Option<Result<T, E>>}
139
137
  */
140
- export declare const step: <O extends Operation, T, Q extends Operation, R>(e: Effect<O, T>, f: (t: T) => Effect<Q, R>) => Effect<O | Q, R>;
138
+ export declare const runPure: <O extends Operation, T, E>(e: Effect<O, T, E>) => Option<Result<T, E>>;
141
139
  /**
142
- * Applies a pure function to an effect's result: the functor `map` of the
143
- * effect monad, and a {@link step} whose continuation performs nothing further.
144
- *
145
- * Prefer it over the `step(e, t => pure(f(t)))` it abbreviates. The two are the
146
- * same value, but they read as different things: a `step` announces another
147
- * link in a sequence of effects, and a trailing pure projection is not one —
148
- * it is where the sequence ends. Saying so in the combinator's name keeps the
149
- * "one name per link" shape of a chain honest about how many effects it runs.
150
- *
151
- * **The operation set does not widen.** The result is `Effect<O, R>`, not
152
- * `Effect<O | Q, R>`, because a pure projection issues no commands — nothing a
153
- * runner has to know how to interpret is added by `f`. That is what separates
154
- * this from `step`, beyond the shorter spelling.
155
- *
156
- * A constant variant (`constStep(e, v)`) is deliberately absent: `mapStep(e,
157
- * () => v)` already reads clearly, and it keeps `v`'s evaluation inside the
158
- * continuation where `step` puts it, rather than moving it to where the
159
- * composition is written.
160
- *
161
- * @type {<O extends Operation, T, R>(e: Effect<O, T>, f: (t: T) => R) => Effect<O, R>}
140
+ * Decodes an effect's next step and dispatches its command to `map`,
141
+ * returning either the final result or the operation's output `R` paired
142
+ * with the continuation. The one world-specific step — `await` for async
143
+ * runners, state threading for sync ones is left to the caller, so every
144
+ * interpreter loop is this skeleton plus a single eliminator line.
145
+ *
146
+ * **An interpreter sees the whole `Result` and must not short-circuit on it.**
147
+ * A runner answers a failed command through the *ordinary* continuation that
148
+ * is what makes `error(notImplemented)` recoverable — so the `done` payload
149
+ * here is `Result<T, E>` rather than the `ok` half. Separating the channels is
150
+ * the composition layer's job, one level up.
151
+ *
152
+ * **The handler is looked up with `at`, never with `map[command]`.**
153
+ * `OperationMap<O, R>` pins `command` to `O[0]` at the type level, but a `Do`
154
+ * node's `command` is runtime data — it can reach an interpreter from a decoded
155
+ * payload or a deserialized continuation, where no type ever constrained it.
156
+ * `map` is an ordinary object, so a plain index read resolves an inherited name
157
+ * (`'constructor'`, `'toString'`, `'hasOwnProperty'`) to the `Object.prototype`
158
+ * member instead of `undefined`, and the line below would then call it with the
159
+ * node's payload: a value the type system promised was `(...payload) => R` turns
160
+ * out to be an arbitrary inherited function, chosen by the same input that
161
+ * supplies its arguments. `at` reads through `getOwnPropertyDescriptor`, which
162
+ * only ever sees own properties, so such a command yields `null` and never a
163
+ * callable.
164
+ *
165
+ * **A `null` handler means one of two different things**, and this is the only
166
+ * place that can still tell them apart. With a total {@link OperationMap} every
167
+ * `O1 extends O` the signature admits has its command in `map`, so a miss means
168
+ * the node's `command` was never the `O1[0]` it claimed to be — a malformed
169
+ * node, and a panic. With a {@link PartialOperationMap} a miss may instead be an
170
+ * operation the runner deliberately does not implement, which is an *outcome*: a
171
+ * program receives `error(notImplemented)` through the ordinary continuation and
172
+ * decides for itself whether to recover, fall back, or panic. {@link partialMatch}
173
+ * is the variant that distinguishes the two; this one keeps the strict reading,
174
+ * because a total map has no second case to distinguish.
175
+ *
176
+ * The two share {@link _matchWith}, so `typeof e === 'function'` still appears
177
+ * in exactly the three places the module header names.
178
+ *
179
+ * @template {Operation} O
180
+ * @template R
181
+ * @param {OperationMap<O, R>} map
162
182
  */
163
- export declare const mapStep: <O extends Operation, T, R>(e: Effect<O, T>, f: (t: T) => R) => Effect<O, R>;
183
+ export declare const match: <O extends Operation, R>(map: OperationMap<O, R>) => <O1 extends O, T, E>(e: Effect<O1, T, E>) => MatchResult<O1, T, E, R>;
164
184
  /**
165
- * Like {@link step}, but keeps the values instead of discarding them: runs `e`
166
- * to get the history `p`, continues with `f(...p)` to get `r`, and yields
167
- * `[r, ...p]` the same history with `r` prepended.
168
- *
169
- * This is what a chain of named intermediate effects cannot otherwise express.
170
- * Each `step`'s continuation sees only the result of the effect it consumes, so
171
- * a later link has no way to reach an earlier one. `historyStep` carries every
172
- * earlier value forward, and the next destructuring names the parts:
185
+ * {@link match} for a runner that is *meant* to lack operations.
186
+ *
187
+ * A command in `commands` with no handler in `map` is a capability this runner
188
+ * does not have: `onMissing` builds the answer and the program resumes with it,
189
+ * which is what lets `O` mean "the operations a computation may request" rather
190
+ * than "the operations every runner implements". A command outside `commands`
191
+ * is still a malformed node and still panics an omitted handler and a garbled
192
+ * `command` are not the same failure, and collapsing them would turn a probable
193
+ * bug into a routine outcome.
194
+ *
195
+ * **`onMissing` is supplied by the caller because only the caller can build an
196
+ * `R`.** `R` is the *runner's* wrapper — `Promise<…>` for an async loop,
197
+ * `(state) => [state, …]` for a state-threading one — not the operation's
198
+ * return type, so this function has no way to construct one. Each runner writes
199
+ * the injector once, next to the loop that defines the shape.
173
200
  *
174
- * ```js
175
- * const b = historyStep(history(a), decodeRevisionBlob(cas))
176
- * const c = step(b, ([revision, hash]) => ...)
177
- * ```
201
+ * @template {Operation} O
202
+ * @template R
203
+ * @param {Commands<O>} commands
204
+ * @param {(command: O[0]) => R} onMissing
205
+ */
206
+ export declare const partialMatch: <O extends Operation, R>(commands: Commands<O>, onMissing: (command: O[0]) => R) => (map: PartialOperationMap<O, R>) => <O1 extends O, T, E>(e: Effect<O1, T, E>) => MatchResult<O1, T, E, R>;
207
+ /**
208
+ * Lifts a value into a successful `Effect` — `pure(ok(v))` written once.
178
209
  *
179
- * Chaining mimics an async function, one `await` per link `const hash = ...`
180
- * then `const revision = ...`, with both still reachable at the end. It takes a
181
- * history and returns one, so it composes with itself to any depth; only the
182
- * entry point needs {@link history}:
210
+ * One of the two entry points into the layer: {@link step} and its siblings
211
+ * compose `Effect`s but cannot produce the first one, and the only other source
212
+ * is an operation's own `Result`.
183
213
  *
184
- * ```js
185
- * const h0 = history(readHash(cas))
186
- * const h1 = historyStep(h0, hash => decodeRevisionBlob(cas)(hash))
187
- * const h2 = historyStep(h1, (revision, hash) => ...)
188
- * ```
214
+ * The error channel is `never`, which is not a special case to handle but the
215
+ * ordinary consequence of the union rules: `never | E` is `E`, so a lifted
216
+ * value composes with any chain without widening its errors.
189
217
  *
190
- * **Newest first.** A position is distance back from the current link, not
191
- * evaluation order, so a destructuring reads reverse-chronologically:
192
- * `([z, y, x]) => ...` binds `x` earliest. Reaching further back costs an index
193
- * rather than a traversal, but a long chain makes the positions hard to count.
194
- * When that starts to hurt, collapse it into a record of named fields
195
- * (`pure({ hash, revision } as const)`) and start a fresh history from there.
196
- *
197
- * `Readonly<P>` on `f`'s rest parameter is load-bearing: inferring `P` from a
198
- * bare rest parameter yields a *mutable*, labelled tuple (`[next: string]`),
199
- * which then rejects the `readonly` tuples every history is built from.
200
- *
201
- * @type {<O extends Operation, P extends readonly unknown[], Q extends Operation, R>(
202
- * e: History<O, P>,
203
- * f: (...p: Readonly<P>) => Effect<Q, R>
204
- * ) => History<O | Q, readonly[R, ...P]>}
218
+ * @type {<T>(v: T) => Effect<never, T, never>}
205
219
  */
206
- export declare const historyStep: <O extends Operation, P extends readonly unknown[], Q extends Operation, R>(e: History<O, P>, f: (...p: Readonly<P>) => Effect<Q, R>) => History<O | Q, readonly [R, ...P]>;
220
+ export declare const pureOk: <T>(v: T) => Effect<never, T, never>;
207
221
  /**
208
- * Starts a history, lifting a plain result into a one-element tuple so that
209
- * {@link historyStep} can extend it.
222
+ * Lifts an error into a failed `Effect` `pure(error(e))` written once, and
223
+ * the mirror of {@link pureOk}, with the success channel `never` instead.
210
224
  *
211
- * Creating a history is the *only* thing this does every later link goes
212
- * through `historyStep`, which is what lets one combinator cover chains of any
213
- * length. Fusing the two (a step that both starts and extends) is what makes
214
- * chains stop composing: such a step nests its predecessor's tuple instead of
215
- * flattening it, so link two would have to be spelled differently from link
216
- * three.
225
+ * This is how a program *originates* a failure: a fallback that has run out of
226
+ * options, or a guard that rejects its input before performing anything. A
227
+ * runner producing `error(notImplemented)` does not go through here that
228
+ * error arrives through an operation's own continuation.
217
229
  *
218
- * @type {<O extends Operation, T>(e: Effect<O, T>) => History<O, readonly[T]>}
230
+ * @type {<E>(e: E) => Effect<never, never, E>}
219
231
  */
220
- export declare const history: <O extends Operation, T>(e: Effect<O, T>) => History<O, readonly [T]>;
232
+ export declare const pureError: <E>(e: E) => Effect<never, never, E>;
221
233
  /**
222
- * @type {<O extends Operation>(command: O[0]) => (...payload: Param<O>) => Effect<O, Return<O>>}
234
+ * Builds the {@link NotImplemented} a runner answers with when it cannot
235
+ * dispatch `command`.
236
+ *
237
+ * It names the command and nothing else. A `Do` node's payload may hold
238
+ * functions — `createServer`'s listener, `sandbox`'s thunk, `test`'s body — so
239
+ * carrying it would break the serializability this error type promises, and the
240
+ * command name is the part a program can act on anyway.
241
+ *
242
+ * @type {(command: string) => NotImplemented}
223
243
  */
224
- export declare const do_: <O extends Operation>(command: O[0]) => (...payload: Param<O>) => Effect<O, Return<O>>;
244
+ export declare const notImplemented: (command: string) => NotImplemented;
225
245
  /**
226
- * Sequentially threads a state value through an effect for each item produced by
227
- * `items`.
246
+ * The normal path: run `e`, and continue with `f` **only** if it succeeded. An
247
+ * `error` short-circuits the rest of the chain and is passed through unchanged.
228
248
  *
229
- * Given `f: item => state => Effect<Q, state>`, `init: S`, and an `items` that
230
- * yields `[x₀, x₁, …]`, builds `step(step(f(x₀)(init), f(x₁)), f(x₂))…` and
231
- * yields a single effect producing the final state.
249
+ * This is the default error propagation the migration exists to provide the
250
+ * structured replacement for exception-style propagation, analogous to Rust's
251
+ * `?`. A sequence therefore reads as its success path, and mentions errors only
252
+ * where it intentionally handles them:
232
253
  *
233
- * Sequential — each step depends on the previous state. Compare to `all`,
234
- * which fans out independent effects.
254
+ * ```js
255
+ * const a = writeFile(...)
256
+ * const b = step(a, () => console('written'))
257
+ * ```
235
258
  *
236
- * **A step variant** (see the two shapes described in this module's header): the
237
- * effect comes first, as in {@link step} and {@link historyStep}. `items` is an
238
- * `Effect<O, List<T>>` rather than a bare `List<T>` because the list a caller
239
- * folds over is normally *produced* by an effect `cas.list()`, a `readdir`.
240
- * Taking the plain list would force every such caller to open a continuation
241
- * just to name the list (`step(cas.list(), foldStep(…))`), which is the nesting
242
- * this module exists to keep out of call sites. A caller that already holds the
243
- * list lifts it with `pure`, which costs a wrapper but no indentation.
259
+ * `'written'` is printed only when `writeFile` returned `ok`. Written with the
260
+ * `Result`-blind `step` this replaced, the same line printed it either way
261
+ * and note that it was the *value-discarding* continuation that hid the
262
+ * hazard, since one that read the value would not have compiled.
244
263
  *
245
- * `O` and `Q` are separate on purpose: the operations needed to produce the list
246
- * are rarely the ones the body performs, and the result unions them.
264
+ * **The error types are unioned** (`E | F`), so `f` may fail in its own way
265
+ * without either side being pre-widened; the operation sets union too, since
266
+ * `f` performs effects of its own.
247
267
  *
248
- * **The argument order is deliberately not `fold`'s** from `fjs/types/list`, and
249
- * the difference is what the two combinators are *for*. `fold` is a data
250
- * pipeline: it is curried `f`-first because the list is the thing being threaded
251
- * through, and nothing about it happens in time. A step variant is a sequencing
252
- * constructit is this module's `do` notation, and reading one top-to-bottom
253
- * is reading the order the program executes in. The effect therefore has to come
254
- * first, because it is what happens first. Currying `f` ahead of `items` would
255
- * put the *body* of the loop above the thing it loops over, which is exactly the
256
- * inversion `do` exists to remove.
268
+ * The body is {@link resultStep} over the one branch this layer is named for:
269
+ * an `error` is handed back as the very tuple it arrived as rather than rebuilt
270
+ * to retag it into a wider type, which is what makes `E | F` expressible instead
271
+ * of forcing both sides to one error type. The continuation is annotated for
272
+ * that reason its two branches have different types, and the annotation
273
+ * states the union they belong to rather than leaving the compiler to infer it
274
+ * from whichever it reads first.
257
275
  *
258
- * That is also why the whole family `step`, `historyStep`, `foldStep`,
259
- * `forEachStep` — takes its effect first and breaks one argument per line when
260
- * it wraps (see this module's header): every such call is a statement list, and
261
- * each line is one statement in execution order.
276
+ * This used to route through an `okStep` exported by the representation
277
+ * module. Nothing
278
+ * else ever called it: the adapter *was* this function's body, one indirection
279
+ * away, so it is written here now and that module has one export fewer.
262
280
  *
263
281
  * @template {Operation} O
264
282
  * @template T
283
+ * @template E
265
284
  * @template {Operation} Q
266
- * @template S
267
- * @param {Effect<O, List<T>>} items
268
- * @param {S} init
269
- * @param {(item: T) => (state: S) => Effect<Q, S>} f
270
- * @returns {Effect<O | Q, S>}
285
+ * @template R
286
+ * @template F
287
+ * @param {Effect<O, T, E>} e
288
+ * @param {(t: T) => Effect<Q, R, F>} f
289
+ * @returns {Effect<O | Q, R, E | F>}
271
290
  */
272
- export declare const foldStep: <O extends Operation, T, Q extends Operation, S>(items: Effect<O, List<T>>, init: S, f: (item: T) => (state: S) => Effect<Q, S>) => Effect<O | Q, S>;
291
+ export declare const step: <O extends Operation, T, E, Q extends Operation, R, F>(e: Effect<O, T, E>, f: (t: T) => Effect<Q, R, F>) => Effect<O | Q, R, E | F>;
273
292
  /**
274
- * Sequentially runs `f(item)` for each item produced by `items`, discarding
275
- * intermediate results. The `void` accumulator sibling of {@link foldStep}, and
276
- * a step variant on the same grounds.
293
+ * The error path: run `e`, and continue with `f` **only** if it failed. An `ok`
294
+ * is preserved unchanged, so the recovery is the only branch that mentions the
295
+ * failure.
277
296
  *
278
- * @type {<O extends Operation, T, Q extends Operation>(items: Effect<O, List<T>>, f: (item: T) => Effect<Q, void>) => Effect<O | Q, void>}
297
+ * The exact mirror of {@link step}: where that unions the error channel and
298
+ * replaces the success type, this unions the success channel (`T | R` — the
299
+ * preserved value or the recovery's) and replaces the error type with `f`'s.
300
+ * Recovering from every error therefore leaves `F` uninhabited, and the type
301
+ * says so.
302
+ *
303
+ * Use it for *intentional* recovery — a fallback operation after a
304
+ * `NotImplemented`, a default for a missing file — never as a blanket
305
+ * "continue anyway"; that is what {@link step}'s propagation already prevents.
306
+ *
307
+ * The local continuation is annotated for the same reason {@link step}'s is:
308
+ * its two branches have different types — `f`'s effect and the untouched `ok`
309
+ * tuple — and the annotation states the union they belong to instead of
310
+ * leaving the compiler to infer it from whichever branch it reads first.
311
+ *
312
+ * @template {Operation} O
313
+ * @template T
314
+ * @template E
315
+ * @template {Operation} Q
316
+ * @template R
317
+ * @template F
318
+ * @param {Effect<O, T, E>} e
319
+ * @param {(err: E) => Effect<Q, R, F>} f
320
+ * @returns {Effect<O | Q, T | R, F>}
279
321
  */
280
- export declare const forEachStep: <O extends Operation, T, Q extends Operation>(items: Effect<O, List<T>>, f: (item: T) => Effect<Q, void>) => Effect<O | Q, void>;
322
+ export declare const catchStep: <O extends Operation, T, E, Q extends Operation, R, F>(e: Effect<O, T, E>, f: (err: E) => Effect<Q, R, F>) => Effect<O | Q, T | R, F>;
281
323
  /**
282
- * A step adapter for the `error` short-circuit: `error` pass it through
283
- * unchanged as `pure`, `ok` continue with `f`. Collapses the hand-written
284
- * `r[0] === 'error' ? pure(r) : f(r[1])` check that recurs at every site
285
- * chaining `Effect<O, Result<T, E>>` steps.
324
+ * Both paths: run `e` and hand `f` the complete `Result`, which then decides
325
+ * what the outcome is. Use it where both branches genuinely matter — a report
326
+ * that records the failure, a retry policy, or the point where a program
327
+ * escalates an error to a panic by `unwrap`ping it.
328
+ *
329
+ * **This is the layer's primitive**, and {@link step} and {@link catchStep} are
330
+ * written in terms of it — each is this function with a continuation that
331
+ * inspects the tag first. It used to be the other way round: a `step` in the
332
+ * representation module composed effects with opaque payloads, and this was
333
+ * that function re-exported under a narrower type. Since every effect carries a
334
+ * `Result`, the opaque spelling described nothing the `Result`-shaped one does
335
+ * not, so the general function lives here now, at the type that says what its
336
+ * continuation receives.
337
+ *
338
+ * `finallyStep` is declined on the principle that a derivable form earns a name
339
+ * by being canonical vocabulary, and that one has not shown it is. It is
340
+ * `resultStep` plus a policy, and adds no expressive power until real consumers
341
+ * demonstrate a repeated policy worth naming.
342
+ *
343
+ * **It is not lazy.** It reads `e`'s shape immediately, so a `Pure` head is
344
+ * forced and `f` is called right there: `resultStep(pure(r), f)` *is* `f(r)`,
345
+ * evaluated where the composition is written rather than where the effect is
346
+ * run. Only the `Do` case defers — the continuation rebuilt around `f` runs
347
+ * when a runner reaches that node.
348
+ *
349
+ * That is sound rather than an oversight, and it is sound only because of
350
+ * `Pure`'s contract: a `Pure` holds a result that has already been computed, so
351
+ * forcing it early observes nothing, repeats nothing, and can throw nothing.
352
+ * Composing never performs a `Do` node, which is where anything real lives.
353
+ * Break the contract — hide work behind the thunk — and merely composing a
354
+ * chain starts running the program.
286
355
  *
287
- * @type {<T, E, O extends Operation, R>(f: (value: T) => Effect<O, Result<R, E>>) => (r: Result<T, E>) => Effect<O, Result<R, E>>}
356
+ * A composition cannot be suspended, and no combinator can fix that:
357
+ * `defer: (() => Effect<O, T, E>) => Effect<O, T, E>` cannot be written, because
358
+ * the `Pure` / `Do` tag must be known before anything runs and the union has no
359
+ * third case meaning "not yet decided". That is inherent to the representation,
360
+ * not a gap in this module's API. A caller that needs to name a composition
361
+ * without performing it yet has to keep the ingredients and defer the step
362
+ * itself.
363
+ *
364
+ * @type {<O extends Operation, T, E, Q extends Operation, R, F>(
365
+ * e: Effect<O, T, E>,
366
+ * f: (r: Result<T, E>) => Effect<Q, R, F>
367
+ * ) => Effect<O | Q, R, F>}
288
368
  */
289
- export declare const okStep: <T, E, O extends Operation, R>(f: (value: T) => Effect<O, Result<R, E>>) => (r: Result<T, E>) => Effect<O, Result<R, E>>;
369
+ export declare const resultStep: <O extends Operation, T, E, Q extends Operation, R, F>(e: Effect<O, T, E>, f: (r: Result<T, E>) => Effect<Q, R, F>) => Effect<O | Q, R, F>;
290
370
  /**
291
- * Runs an effect that reaches its value without performing a command: `[t]` for
292
- * a {@link Pure}, empty for a {@link Do}. Forces the thunk in the `Pure` case,
293
- * which {@link Pure}'s contract makes free of consequence.
294
- *
295
- * The eliminator for callers that expect no operations at all — the other side
296
- * of {@link match}, which is for callers that intend to perform them.
371
+ * Applies a pure function to the `ok` value, passing an `error` through
372
+ * unchanged: the functor `map` of this layer, and a {@link step} whose
373
+ * continuation performs nothing further.
297
374
  *
298
- * **The result is tagged on purpose.** Returning `T | null` would collapse two
299
- * distinct outcomes whenever `T` itself admits `null`: `runPure(pure(null))` and
300
- * `runPure(someDo)` would both be `null`, so a caller asserting `null` would
301
- * accept an effect that unexpectedly stopped at a command exactly the case
302
- * this exists to rule out. `Option<T>` keeps them apart: `[null]` is a pure
303
- * `null`, `[]` is a `Do`.
375
+ * A trailing pure projection is where a sequence *ends*, not another link in
376
+ * it, and spelling it as a step misreports how many effects a chain runs
377
+ * (`./todo/map-step-combinator.md`). Without this, every such site would
378
+ * regress to exactly that spelling, now with a `pureOk` inside it.
304
379
  *
305
- * `O` stays generic rather than narrowing to `Effect<never, T>`. `Effect` is
306
- * covariant in `O`, so `Effect<never, T>` is assignable to `Effect<O, T>` and
307
- * not the reverse — a continuation's result is always the wider type and would
308
- * be rejected. `Do<never, T>` is uninhabited besides, which would make the empty
309
- * case unreachable without a cast.
380
+ * **The operation set does not widen**: a pure projection issues no commands. Neither does the error channel — `f` cannot
381
+ * fail, so a chain that only projects its value keeps the errors it already
382
+ * had.
310
383
  *
311
- * @type {<O extends Operation, T>(e: Effect<O, T>) => Option<T>}
384
+ * @type {<O extends Operation, T, E, R>(e: Effect<O, T, E>, f: (t: T) => R) => Effect<O, R, E>}
312
385
  */
313
- export declare const runPure: <O extends Operation, T>(e: Effect<O, T>) => Option<T>;
386
+ export declare const mapStep: <O extends Operation, T, E, R>(e: Effect<O, T, E>, f: (t: T) => R) => Effect<O, R, E>;
314
387
  /**
315
- * Decodes an effect's next step and dispatches its command to `map`,
316
- * returning either the final result or the operation's output `R` paired
317
- * with the continuation. The one world-specific step — `await` for async
318
- * runners, state threading for sync ones — is left to the caller, so every
319
- * interpreter loop is this skeleton plus a single eliminator line.
320
- *
321
- * **The handler is looked up with `at`, never with `map[command]`.**
322
- * `OperationMap<O, R>` pins `command` to `O[0]` at the type level, but a `Do`
323
- * node's `command` is runtime data — it can reach an interpreter from a decoded
324
- * payload or a deserialized continuation, where no type ever constrained it.
325
- * `map` is an ordinary object, so a plain index read resolves an inherited name
326
- * (`'constructor'`, `'toString'`, `'hasOwnProperty'`) to the `Object.prototype`
327
- * member instead of `undefined`, and the line below would then call it with the
328
- * node's payload: a value the type system promised was `(...payload) => R` turns
329
- * out to be an arbitrary inherited function, chosen by the same input that
330
- * supplies its arguments. `at` reads through `getOwnPropertyDescriptor`, which
331
- * only ever sees own properties, so such a command yields `null` and never a
332
- * callable.
388
+ * Applies a pure function to the whole {@link Result}: the both-branches
389
+ * sibling of {@link mapStep}, and the {@link resultStep} whose continuation
390
+ * performs nothing further.
391
+ *
392
+ * Reach for it where a projection genuinely decides the outcome rather than
393
+ * transforming a value — turning any answer into a fixed one, replacing a
394
+ * channel wholesale, re-tagging a failure. Where only the success is being
395
+ * transformed, {@link mapStep} says so and leaves the channel alone.
396
+ *
397
+ * **Neither channel is preserved**, which is the difference that matters
398
+ * against `mapStep`: `f` returns a `Result<R, F>` of its own, so a caller can
399
+ * discard errors here. That is exactly what makes it the honest spelling for a
400
+ * site that means to the discarding is written down, in a function that says
401
+ * it takes both branches, instead of being implied by a value-shaped `map` that
402
+ * quietly received a `Result`.
403
+ *
404
+ * Its two output channels are read off `f`'s return type with {@link OkOf} /
405
+ * {@link ErrOf}, for the reason `pure` gives: inference against the `Result`
406
+ * union cannot place a one-sided return, so a projection that always answers
407
+ * `ok` would otherwise acquire an error channel it never produces.
408
+ *
409
+ * @type {<O extends Operation, T, E, R extends Result<unknown, unknown>>(
410
+ * e: Effect<O, T, E>,
411
+ * f: (r: Result<T, E>) => R
412
+ * ) => Effect<O, OkOf<R>, ErrOf<R>>}
413
+ */
414
+ export declare const resultMapStep: <O extends Operation, T, E, R extends Result<unknown, unknown>>(e: Effect<O, T, E>, f: (r: Result<T, E>) => R) => Effect<O, OkOf<R>, ErrOf<R>>;
415
+ /**
416
+ * Empties the error channel by **panicking** on it: `ok` values continue
417
+ * unchanged, an `error` is thrown as `summary(e)`, and what comes back is an
418
+ * `Effect<O, T, never>` — a `never` that is earned rather than asserted, since
419
+ * the only way past this point is success.
420
+ *
421
+ * This is the program exercising its right to treat a failure as fatal, and it
422
+ * is a policy — not a conversion. It belongs at a site that genuinely has no
423
+ * answer to the failure: a build tool that cannot read its own sources, a
424
+ * proof whose fixture is missing. Where a caller could do something else,
425
+ * {@link catchStep} or {@link resultStep} is the honest spelling, and a chain
426
+ * that merely passes the failure along wants {@link step}.
427
+ *
428
+ * **`summary` is what names the errors being panicked on, and it is required
429
+ * for that reason rather than for the message.** Without it this function was
430
+ * generic in `E` and therefore compiled however far a channel widened: one
431
+ * fallible read added upstream enlarged what every downstream call crashed on,
432
+ * silently. A renderer written for a particular channel cannot accept a wider
433
+ * one — parameters are contravariant — so widening becomes a compile error at
434
+ * the site that chose to panic, which is the site that has to choose again.
435
+ *
436
+ * The `IoChannel` renderer is `errorSummary` (`./node/module.f.mjs`); pass a
437
+ * narrower one where the channel is narrower. An inline `e => String(e)`
438
+ * accepts anything and gives the old behaviour back — that is an escape hatch,
439
+ * and being written out at the call site is the point.
440
+ *
441
+ * This being one greppable name still matters: every occurrence is a site that
442
+ * has chosen to panic, so the choice can be reviewed. What the name alone
443
+ * could not do is tell a reviewer that a site's *scope* had grown since they
444
+ * last looked at it, which is what the argument adds.
445
+ *
446
+ * @type {<O extends Operation, T, E>(e: Effect<O, T, E>, summary: (e: E) => string) => Effect<O, T, never>}
447
+ */
448
+ export declare const unwrapStep: <O extends Operation, T, E>(e: Effect<O, T, E>, summary: (e: E) => string) => Effect<O, T, never>;
449
+ /**
450
+ * Starts a history from a fallible effect, lifting its `ok` value into a
451
+ * one-element tuple that {@link historyStep} extends — the entry point a chain
452
+ * needs exactly once.
333
453
  *
334
- * A `null` handler is an invariant violation, not an outcome: every `O1 extends
335
- * O` the signature admits has its command in `map`, so reaching it means the
336
- * node's `command` was never the `O1[0]` it claimed to be. It therefore throws
337
- * (`assert`) rather than widening {@link MatchResult} with a variant no
338
- * type-correct caller could ever observe a runner cannot resume a command it
339
- * has no handler for, so there is nothing for a recovery branch to do.
454
+ * @type {<O extends Operation, T, E>(e: Effect<O, T, E>) => Effect<O, readonly[T], E>}
455
+ */
456
+ export declare const history: <O extends Operation, T, E>(e: Effect<O, T, E>) => Effect<O, readonly [T], E>;
457
+ /**
458
+ * Like {@link step}, but carries the values forward instead of discarding
459
+ * them: runs `e` for the history `p`, continues with `f(...p)` for `r`, and
460
+ * yields `[r, ...p]`.
461
+ *
462
+ * This is what keeps a **fallible** chain flat. Each `step`'s continuation sees
463
+ * only the value it consumes, so a later link cannot reach an earlier one, and
464
+ * the alternative — nesting so the inner continuation closes over the outer
465
+ * one's parameter — is what `fjs/AGENTS.md` §3.4 rules out. A `Result`-blind
466
+ * `historyStep` could not serve: it carried each link's `Result` into the tuple
467
+ * rather than its value, so every later link had to destructure results it had
468
+ * no intention of handling. That is why this one exists and that one does not.
469
+ *
470
+ * The history holds `ok` values only. An `error` short-circuits the chain, so a
471
+ * failed link contributes nothing to the tuple — which is the point: a later
472
+ * link reads earlier values without asking whether they are there.
340
473
  *
341
474
  * @template {Operation} O
475
+ * @template {readonly unknown[]} P
476
+ * @template E
477
+ * @template {Operation} Q
342
478
  * @template R
343
- * @param {OperationMap<O, R>} map
479
+ * @template F
480
+ * @param {Effect<O, P, E>} e
481
+ * @param {(...p: Readonly<P>) => Effect<Q, R, F>} f
482
+ * @returns {Effect<O | Q, readonly[R, ...P], E | F>}
344
483
  */
345
- export declare const match: <O extends Operation, R>(map: OperationMap<O, R>) => <O1 extends O, T>(
484
+ export declare const historyStep: <O extends Operation, P extends readonly unknown[], E, Q extends Operation, R, F>(e: Effect<O, P, E>, f: (...p: Readonly<P>) => Effect<Q, R, F>) => Effect<O | Q, readonly [R, ...P], E | F>;
346
485
  /**
347
- * @template {O} O1
486
+ * Threads a state through one effect per item, short-circuiting on the first
487
+ * `error`.
488
+ *
489
+ * **`items` is an `Effect` like everything else here.** Its payload was once
490
+ * unwrapped, on the argument that a held list has no error channel and
491
+ * requiring one would mean lifting at every call site. Lifting is one `pureOk`
492
+ * call, and that version made the *fallible* producer pay instead:
493
+ * `fjs/cas/cli` wrapped the whole fold in a `step` whose only job was to unwrap
494
+ * `list()` so `pure` could wrap it again. A producer that can fail now feeds
495
+ * the fold directly, and one that cannot is unaffected when it later can.
496
+ *
497
+ * **The argument order is deliberately not `fold`'s** from `fjs/types/list`, and
498
+ * the difference is what the two combinators are *for*. `fold` is a data
499
+ * pipeline: it is curried `f`-first because the list is the thing being threaded
500
+ * through, and nothing about it happens in time. A step variant is a sequencing
501
+ * construct — this module's `do` notation — and reading one top-to-bottom is
502
+ * reading the order the program executes in. The effect therefore has to come
503
+ * first, because it is what happens first. Currying `f` ahead of `items` would
504
+ * put the *body* of the loop above the thing it loops over, which is exactly the
505
+ * inversion `do` exists to remove.
506
+ *
507
+ * That is also why the whole family — {@link step}, {@link historyStep},
508
+ * `foldStep`, {@link forEachStep} — takes its effect first and breaks one
509
+ * argument per line when it wraps: every such call is a statement list, and each
510
+ * line is one statement in execution order.
511
+ *
512
+ * @template {Operation} O
348
513
  * @template T
349
- * @param {Effect<O1, T>} e
350
- * @returns {MatchResult<O1, T, R>}
514
+ * @template {Operation} Q
515
+ * @template S
516
+ * @template E
517
+ * @param {Effect<O, List<T>, E>} items
518
+ * @param {S} init
519
+ * @param {(item: T) => (state: S) => Effect<Q, S, E>} f
520
+ * @returns {Effect<O | Q, S, E>}
521
+ */
522
+ export declare const foldStep: <O extends Operation, T, Q extends Operation, S, E>(items: Effect<O, List<T>, E>, init: S, f: (item: T) => (state: S) => Effect<Q, S, E>) => Effect<O | Q, S, E>;
523
+ /**
524
+ * Runs `f(item)` for each item in order, stopping at the first failure and
525
+ * propagating it. The `void` accumulator sibling of {@link foldStep}.
526
+ *
527
+ * Stopping is the difference against the `Result`-blind `forEachStep` this
528
+ * replaced: that one ran every item whatever each answered, because its `void`
529
+ * accumulator had nothing to carry a failure in — and TypeScript's `void`
530
+ * return position accepts a `Result`-valued effect silently, so the discard
531
+ * does not even show up as a type error.
532
+ *
533
+ * @type {<O extends Operation, T, Q extends Operation, E>(
534
+ * items: Effect<O, List<T>, E>,
535
+ * f: (item: T) => Effect<Q, void, E>
536
+ * ) => Effect<O | Q, void, E>}
351
537
  */
352
- e: Effect<O1, T>) => MatchResult<O1, T, R>;
538
+ export declare const forEachStep: <O extends Operation, T, Q extends Operation, E>(items: Effect<O, List<T>, E>, f: (item: T) => Effect<Q, void, E>) => Effect<O | Q, void, E>;