A bit of library clean-up
This commit is contained in:
@@ -10,39 +10,7 @@ bytesTail = matchList nothing (_ r : just r)
|
||||
byteEq? = equal?
|
||||
bytesLength = length
|
||||
bytesAppend = append
|
||||
|
||||
bytesTake_ = y (self remaining n i :
|
||||
matchList
|
||||
t
|
||||
(h r :
|
||||
matchBool
|
||||
t
|
||||
(pair h (self r n (succ i)))
|
||||
(equal? i n))
|
||||
remaining)
|
||||
|
||||
bytesTake = n bytes : bytesTake_ bytes n 0
|
||||
|
||||
bytesDrop_ = y (self remaining n i :
|
||||
matchList
|
||||
t
|
||||
(_ r :
|
||||
matchBool
|
||||
remaining
|
||||
(self r n (succ i))
|
||||
(equal? i n))
|
||||
remaining)
|
||||
|
||||
bytesDrop = n bytes : bytesDrop_ bytes n 0
|
||||
|
||||
bytesSplitAt = n bytes : pair (bytesTake n bytes) (bytesDrop n bytes)
|
||||
|
||||
bytesEq? = y (self xs ys :
|
||||
matchList
|
||||
(matchList true (_ _ : false) ys)
|
||||
(xh xt :
|
||||
matchList
|
||||
false
|
||||
(yh yt : and? (byteEq? xh yh) (self xt yt))
|
||||
ys)
|
||||
xs)
|
||||
bytesTake = take
|
||||
bytesDrop = drop
|
||||
bytesSplitAt = splitAt
|
||||
bytesEq? = equal?
|
||||
|
||||
16
lib/io.tri
16
lib/io.tri
@@ -91,8 +91,8 @@ onResult_ = action errCase okCase :
|
||||
-- Convenience helpers
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
||||
print = s : bind (putStr s) (_ : pure t)
|
||||
putStrLn = s : bind (putStr (append s "\n")) (_ : pure t)
|
||||
print = s : void (putStr s)
|
||||
putStrLn = s : void (putStr (append s "\n"))
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Result-aware file helpers
|
||||
@@ -117,18 +117,12 @@ writeFileOrPrintError = (path contents okCase :
|
||||
okCase)
|
||||
|
||||
copyFile = (src dst :
|
||||
bind (readFile src)
|
||||
(result :
|
||||
matchResult
|
||||
onResult (readFile src)
|
||||
(err rest : putStrLn (append "Read failed: " err))
|
||||
(contents rest :
|
||||
bind (writeFile dst contents)
|
||||
(wr :
|
||||
matchResult
|
||||
onResult (writeFile dst contents)
|
||||
(err rest : putStrLn (append "Write failed: " err))
|
||||
(ok rest : pure t)
|
||||
wr))
|
||||
result))
|
||||
(_ _ : pure t)))
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Resource-safe combinators
|
||||
|
||||
10
lib/list.tri
10
lib/list.tri
@@ -157,8 +157,6 @@ partition_ = y (self pred xs trues falses :
|
||||
|
||||
partition = pred xs : partition_ pred xs t t
|
||||
|
||||
partition = pred xs : partition_ pred xs t t
|
||||
|
||||
strLength = length
|
||||
strAppend = append
|
||||
strEq? = equal?
|
||||
@@ -191,11 +189,11 @@ contains? = y (self needle haystack :
|
||||
|
||||
lines_ = y (self str :
|
||||
matchList
|
||||
(acc current : append acc [(reverse current)])
|
||||
(acc current : snoc (reverse current) acc)
|
||||
(h r :
|
||||
acc current :
|
||||
matchBool
|
||||
(self r (append acc [(reverse current)]) t)
|
||||
(self r (snoc (reverse current) acc) t)
|
||||
(self r acc (pair h current))
|
||||
(equal? h 10))
|
||||
str)
|
||||
@@ -213,14 +211,14 @@ words_ = y (self str :
|
||||
(acc current :
|
||||
matchBool
|
||||
acc
|
||||
(append acc [(reverse current)])
|
||||
(snoc (reverse current) acc)
|
||||
(emptyList? current))
|
||||
(h r :
|
||||
acc current :
|
||||
matchBool
|
||||
(matchBool
|
||||
(self r acc current)
|
||||
(self r (append acc [(reverse current)]) t)
|
||||
(self r (snoc (reverse current) acc) t)
|
||||
(emptyList? current))
|
||||
(self r acc (pair h current))
|
||||
(equal? h 32))
|
||||
|
||||
@@ -1,262 +0,0 @@
|
||||
# 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.
|
||||
|
||||
Reference in New Issue
Block a user