263 lines
5.1 KiB
Markdown
263 lines
5.1 KiB
Markdown
# Standard Library TODO / Expansion Plan
|
|
|
|
> Foundational expansions that improve safety, composability, and ergonomics across the entire tricu ecosystem.
|
|
|
|
---
|
|
|
|
## 1. Extract a `maybe.tri` / Option layer
|
|
|
|
**Motivation:** `head`, `tail`, `last`, `nth`, `bytesHead`, and `bytesTail` currently return `t` on failure, which is ambiguous because `t` is also a valid tree value. A proper option layer makes all of these APIs safer and self-describing.
|
|
|
|
**Additions:**
|
|
|
|
```tricu
|
|
nothing = t
|
|
just = x : t x
|
|
|
|
matchMaybe = nothingCase justCase maybe :
|
|
triage
|
|
nothingCase
|
|
justCase
|
|
(_ _ : nothingCase)
|
|
maybe
|
|
|
|
maybe = default f m : matchMaybe default f m
|
|
maybeMap = f m : matchMaybe nothing (x : just (f x)) m
|
|
maybeBind = m f : matchMaybe nothing f m
|
|
maybeOr = default m : matchMaybe default id m
|
|
maybe? = matchMaybe false (_ : true)
|
|
```
|
|
|
|
**Then update existing list/bytes primitives:**
|
|
|
|
```tricu
|
|
headMaybe
|
|
lastMaybe
|
|
nthMaybe
|
|
bytesHead
|
|
bytesTail
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Move `Result` combinators from `binary.tri` into `base.tri`
|
|
|
|
**Motivation:** `Result` is defined in `base.tri`, but `mapResult` and `bindResult` currently live in `binary.tri`. This makes them unavailable to IO, socket, and file helpers unless every consumer imports binary parsing.
|
|
|
|
**Move / add to `base.tri`:**
|
|
|
|
```tricu
|
|
mapResult = f result :
|
|
matchResult
|
|
(code rest : err code rest)
|
|
(value rest : ok (f value) rest)
|
|
result
|
|
|
|
bindResult = result f :
|
|
matchResult
|
|
(code rest : err code rest)
|
|
(value rest : f value rest)
|
|
result
|
|
|
|
resultOr = default result :
|
|
matchResult
|
|
(_ _ : default)
|
|
(value _ : value)
|
|
result
|
|
|
|
resultMapErr = f result :
|
|
matchResult
|
|
(code rest : err (f code) rest)
|
|
(value rest : ok value rest)
|
|
result
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Add basic numeric comparison and arithmetic
|
|
|
|
**Motivation:** Without comparison and arithmetic, list slicing, parser limits, counters, socket loops, and CLI utilities are awkward or impossible.
|
|
|
|
**Priority order:**
|
|
|
|
1. `isZero?`
|
|
2. `add`
|
|
3. `sub`
|
|
4. `lt?`
|
|
5. `lte?`
|
|
6. `mul`
|
|
|
|
Even simple Peano / binary-tree versions unlock a huge amount of functionality.
|
|
|
|
---
|
|
|
|
## 4. Expand `list.tri` with safer and more complete primitives
|
|
|
|
**Motivation:** `reverse` currently uses `append` recursively, which is quadratic. Many common operations (`take`, `drop`, `concatMap`) are missing entirely.
|
|
|
|
**High-impact additions:**
|
|
|
|
```tricu
|
|
take
|
|
drop
|
|
splitAt
|
|
concatMap
|
|
find
|
|
partition
|
|
zipWith
|
|
```
|
|
|
|
**Performance fix:**
|
|
|
|
```tricu
|
|
reverse_ = y (self xs acc :
|
|
matchList
|
|
acc
|
|
(h r : self r (pair h acc))
|
|
xs)
|
|
|
|
reverse = xs : reverse_ xs t
|
|
```
|
|
|
|
This is low-effort, high-impact because `reverse` is already used by `binary.tri` and `conversions.tri`.
|
|
|
|
---
|
|
|
|
## 5. Add string aliases / helpers
|
|
|
|
**Motivation:** IO and CLI programs almost always need line/string manipulation. Socket protocols are also easier with canonical string utilities.
|
|
|
|
**Highest value:**
|
|
|
|
```tricu
|
|
startsWith?
|
|
contains?
|
|
lines
|
|
unlines
|
|
```
|
|
|
|
Also consider:
|
|
|
|
```tricu
|
|
strLength
|
|
strAppend
|
|
strEq?
|
|
strEmpty?
|
|
words
|
|
unwords
|
|
endsWith?
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Expand `binary.tri` into a small parser-combinator layer
|
|
|
|
**Motivation:** `binary.tri` already has `readU8`, `readBytes`, `expectBytes`, etc. A thin combinator layer makes binary parsing much more ergonomic and reusable for protocols/file formats.
|
|
|
|
**Suggested additions:**
|
|
|
|
```tricu
|
|
pureParser = value bs : ok value bs
|
|
failParser = code bs : err code bs
|
|
|
|
mapParser = mapResult
|
|
bindParser = bindResult
|
|
thenParser = p q : bindResult p (_ : q)
|
|
orParser = p q bs :
|
|
matchResult
|
|
(_ _ : q bs)
|
|
(value rest : ok value rest)
|
|
(p bs)
|
|
```
|
|
|
|
Then common parsers:
|
|
|
|
```tricu
|
|
readWhile
|
|
readUntil
|
|
readRemaining
|
|
peekU8
|
|
eof?
|
|
expectAscii
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Add endian / int conversion helpers
|
|
|
|
**Motivation:** `readU16BEBytes` and `readU32BEBytes` return raw byte lists. Either rename them or add actual numeric decoding.
|
|
|
|
**Suggested additions:**
|
|
|
|
```tricu
|
|
u16BE
|
|
u16LE
|
|
u32BE
|
|
u32LE
|
|
|
|
readU16BE
|
|
readU16LE
|
|
readU32BE
|
|
readU32LE
|
|
```
|
|
|
|
---
|
|
|
|
## 8. Add resource-safe IO helpers
|
|
|
|
**Motivation:** Sockets, files, and process-like resources need predictable cleanup.
|
|
|
|
```tricu
|
|
finally = action cleanup :
|
|
bind action (result :
|
|
bind cleanup (_ :
|
|
pure result))
|
|
|
|
bracket = acquire release use :
|
|
bind acquire (resource :
|
|
bind (use resource) (result :
|
|
bind (release resource) (_ :
|
|
pure result)))
|
|
```
|
|
|
|
---
|
|
|
|
## 9. Add socket server loops
|
|
|
|
**Motivation:** Almost every socket example repeats the same `forever` + `withAccepted_` scaffolding.
|
|
|
|
```tricu
|
|
serveForever = server handler :
|
|
forever
|
|
(withAccepted_ server
|
|
(err : pure t)
|
|
(client peer :
|
|
fork (handler client peer)))
|
|
```
|
|
|
|
Also consider:
|
|
|
|
```tricu
|
|
connectTo = addr port :
|
|
onOk_ socket (client :
|
|
onOk_ (connect client addr port) (_ :
|
|
pure (ok client)))
|
|
```
|
|
|
|
---
|
|
|
|
## 10. Add a curated `prelude.tri`
|
|
|
|
**Motivation:** As libraries grow, users need a stable starting point.
|
|
|
|
```tricu
|
|
!import "base.tri" !Local
|
|
!import "maybe.tri" !Local
|
|
!import "list.tri" !Local
|
|
!import "bytes.tri" !Local
|
|
!import "conversions.tri" !Local
|
|
```
|
|
|
|
This gives a standard baseline without importing IO / socket / binary by default.
|
|
|