Edva unifies booleans, optional values, fallible statuses, and result types into a single two-slot algebraic construct: the ramification (ram). Every ramification has a positive (first) slot and a negative (second) slot.
10.1 The four ramification layouts and ABI
Layout
Type Syntax
Positive (1st Slot)
Negative (2nd Slot)
Runtime ABI & Niche Lowering
Role
RamNN
<>
<+> (unit)
<-> (unit)
Unboxed i1 (1 = <+>, 0 = <->)
Boolean Flag (built-in, no #type needed)
RamPN
< T | >
<+ val +> (T)
<--> (unit)
Null-pointer niche (ptr, null = <-->) for String/Record; otherwise { i1, T }
Option (value or absence)
RamNP
< | E >
<++> (unit)
<- err -> (E)
Null-pointer niche (ptr, null = <++>) for String/Record/Error; otherwise { i1, E }
All payload constructors close with +> or -> (never bare >), ensuring relational comparisons inside payloads (<+ a > b ->) are unambiguous:
Target Shape
Positive Slot Constructor
Negative Slot Constructor
Coercion Rule
<> (RamNN)
<+>
<->
Never implicitly coerces to <++> or <-->
< T | > (RamPN)
<+ val +>
<-->
Implicit | <--> synthesized in non-exhaustive expression choices
< | E > (RamNP)
<++>
<- err ->
Implicit | <++> synthesized in non-exhaustive expression choices
< T | E > (RamPP)
<+ val ->
<- err +>
Both slots carry typed payloads
#useio#typeMaybeInt< Int | >#typeStatus< | String >#typeOutcome< Int | String >flag =<+>opt =MaybeInt(<+42+>)stat =Status(<++>)res =Outcome(<+100->)io::out $ (flag, opt | _ |0, stat |"ok"| _, res!!)
10.2 Operations on flags and ramifications
Operation
Syntax
Input Type
Result Type
Semantics & Diagnostics
Logical NOT
!f
<>
<>
Inverts <+>\(\leftrightarrow\)<-> (E3008 on non-flag types)
Logical AND / OR
a && b, a || b
<> or compatible ram
Same
Short-circuiting conjunction / disjunction
Flag extraction
<>(r) / !<>(r)
Any ram r
<>
Discards payloads and returns <+> if r is positive (!<>(r) negates)
Positional choice
r | pos | neg
Any ram r
Unified branch type
1st | matches positive slot; 2nd | matches negative slot (_ or x => binds payload)
Skip-first choice
r !| neg_body
< | E > / <>
Unified type
Sugar for r | (void) | neg_body (e.g. arr(i) = v !| _ panics on OOB write)
Unwrap or abort
r!!
< T | E > or < T | >
T
Extracts positive payload T or aborts on negative slot (E3091 on <|E> / <>)
Unwrap or propagate
r--!
< T | E >, < T | >, < | E >, <>
T or ()
Extracts positive slot or early-returns the negative ram from the enclosing function
Monadic bind
r $>> cont
< T | E > or < T | >
Ram returned by cont
Calls cont(val) on positive slot; propagates negative slot unchanged (E3091 if cont non-ram)
Early return sugar
c |->c |+>c |-->c |++>
c: <>
() (returns from fn)
Early-returns <->, <+>, <-->, or <++> when c is <+>
#useioparse_pos: Int=>< Int | String >parse_pos = n => n !>0|--|<-"non-positive"+><+ n *10->double_pos: Int=>< Int | String >double_pos = n => v = parse_pos(n)--!<+ v *2->io::out $ double_pos(3) | _ |-1// 60io::out $ double_pos(-1) | _ |-1// -1
10.3 The Error type and I/O conventions
Error is the built-in structured diagnostic record used in < T | Error > and < | Error >:
Field / Form
Type / Syntax
Semantics
err.code
Int
Numeric error code (POSIX errno, HTTP status, or application code)
err.msg
String
Human-readable diagnostic message
err.file, err.line, err.col
String, Int, Int
Source location automatically captured by Error(code, msg) at the call site
err.context
(Int, Int)
Auxiliary context tuple (defaults to (0, 0))
Error(code, msg)
Constructor
Captures caller file, line, col automatically
r | _ | _ on < T | Error >
Fatal negative _
Extracting a negative Error slot with bare _ aborts execution with E4011 (like r!!); bind a named parameter (| err => ...) to handle recoverably