Files
tricu/notes/stdlib-todo.md

5.1 KiB

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:

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:

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:

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:

take
drop
splitAt
concatMap
find
partition
zipWith

Performance fix:

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:

startsWith?
contains?
lines
unlines

Also consider:

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:

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:

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:

u16BE
u16LE
u32BE
u32LE

readU16BE
readU16LE
readU32BE
readU32LE

8. Add resource-safe IO helpers

Motivation: Sockets, files, and process-like resources need predictable cleanup.

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.

serveForever = server handler :
  forever
    (withAccepted_ server
      (err : pure t)
      (client peer :
        fork (handler client peer)))

Also consider:

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.

!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.