You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I love the Go build system but I really like F# (correctness) and Dingo Lang https://github.com/MadAppGang/dingo (another Go transpiled language) but Lisette is closer to what I'm looking for as I'm desperate for a Go-based language that has a few features that could make it a winner -- so I've written four examples that could help build out Lisette.
Below is the complete, revised recommendation for the four features in Lisette. I’ve integrated your exact example for safe navigation and updated all sections for consistency, clarity, and alignment with Lisette’s current safety model (no nil, Option<T> / Result<T, E>, exhaustive match, ? propagation, immutable defaults, and clean Go output).
Description of the Four Additions
These four features create a powerful, cohesive upgrade that brings Lisette closer to F#’s expressive functional style (domain modeling, monadic workflows) while adding Dingo-style everyday ergonomics — all without compromising the strong safety guarantees in safety.md (elimination of nil, exhaustive matching, zero-cost abstractions, and safe Go interop).
Units of Measure
Zero-runtime-cost numeric tags that prevent mixing incompatible values (e.g., USD vs BTC) at compile time.
Safe Navigation ?. and Coalescing ?? Operators
Concise syntax for chaining Option<T> accesses and providing defaults, dramatically reducing nested match boilerplate.
Computation Expressions
Builder blocks (result { }, option { }, task { }) that allow linear let!, do!, return, and return! syntax for monadic code.
Active Patterns
User-defined named patterns that extend match with reusable custom decomposition and validation logic.
All features desugar cleanly to existing Lisette constructs or simple Go code, introduce no runtime overhead, and enhance the “make invalid states unrepresentable” philosophy from your safety documentation.
1. Units of Measure
Concrete Syntax Proposal:
[Measure]
type USD
[Measure]
type BTC
[Measure]
type kg
// Generic form
type Money<'u> = decimal<'u>
Usage Examples:
let price: decimal<USD> = 1499.99
let btcAmount: decimal<BTC> = 0.042
let rate: decimal<USD/BTC> = 65000.0
let usdValue = btcAmount * rate // type: decimal<USD>
// price + btcAmount // compile error: unit mismatch
Desugaring to Go:
Units are fully erased at compile time. All values become plain float64 / decimal (or equivalent) with type checking performed only by the Lisette compiler.
Benefits for Lisette: Excellent for finance, crypto, scientific computing, or any domain with typed quantities. It pairs naturally with your enums and exhaustive matching to make currency or unit errors impossible at runtime.
2. Safe Navigation ?. and Coalescing ?? Operators
Concrete Syntax Proposal:
// With proposed ?. and ?? (much cleaner)
let city = user?.address?.city ?? "unknown"
Current style (already safe thanks to Option):
let city = match user.address with
| Some addr -> match addr.city with
| Some c -> c
| None -> "unknown"
| None -> "unknown"
Additional Examples:
let fullName = user?.profile?.getFullName() ?? "Anonymous"
let data = fetchUser(id)?.name ?? "Guest"
Desugaring (to current Lisette + Go):
The ?. operator desugars to nested match on Option (or equivalent if let chains). The ?? operator becomes a fallback using unwrap_or / unwrap_or_else.
Final Go output is a clear series of if statements with proper Option unwrapping, preserving full safety and readability.
Benefits for Lisette: Your safety model already forces Option<T> instead of nil. This sugar makes deeply nested Option code far more readable and concise while keeping every access explicitly safe and exhaustive. It brings Dingo-like ergonomics without weakening any guarantees from safety.md.
let! x = expr → bind / map chain (leveraging your existing ? where appropriate)
return x → wrap in Ok / Some / etc.
return! expr → direct return of the monadic value
The entire block desugars to nested calls that the compiler optimizes into clean control flow.
Desugaring to Go (example for result { }):
The builder expands into explicit if + match or Result handling chains, producing readable Go code similar to manual error checking but without duplication.
Benefits for Lisette: Extends your ? operator into full, readable monadic workflows for error handling, validation, async, or tasks. Complex logic becomes linear and F#-like while desugaring to efficient, safe Go.
4. Active Patterns
Concrete Syntax Proposal:
// Full active pattern
let (|Even|Odd|) (n: int) =
if n % 2 == 0 { Even } else { Odd }
// Partial active pattern
let (|ValidEmail|_) (s: string) =
if isValidEmailFormat(s) { Some(s) } else { None }
// Parameterized example
let (|PositiveAmount|NegativeAmount|Zero|) (amt: decimal<USD>) =
match amt {
_ if amt > 0.0 => PositiveAmount(amt),
_ if amt < 0.0 => NegativeAmount(amt),
_ => Zero,
}
Usage:
match amount {
Even => "even",
Odd => "odd",
}
match inputEmail {
ValidEmail(email) => process(email),
_ => Err("invalid email"),
}
match balance {
PositiveAmount(val) => ...,
NegativeAmount(val) => ...,
Zero => ...,
}
Desugaring:
Active patterns compile to helper functions. The match expression is rewritten to call these functions and then match on their returned value (Option for partial patterns or a simple variant for full ones). Exhaustiveness checking remains fully enforced.
Benefits for Lisette: Extends your excellent pattern-matching infrastructure (08-pattern-matching.md) with reusable, domain-specific logic (e.g., currency validation, parsing rules). Code stays expressive, safe, and exhaustive.
Units of Measure – Clean type-system extension with zero runtime cost.
Active Patterns – Natural extension of existing match.
Computation Expressions – Most powerful addition, building on ? and builders.
Together, these features make Lisette feel like a modern fusion of F# expressiveness and Dingo convenience while staying true to its Rust-inspired safety and Go compilation target. They require mostly parser, type-checker, and desugaring work — no changes to the runtime or Go output semantics.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
I love the Go build system but I really like F# (correctness) and Dingo Lang https://github.com/MadAppGang/dingo (another Go transpiled language) but Lisette is closer to what I'm looking for as I'm desperate for a Go-based language that has a few features that could make it a winner -- so I've written four examples that could help build out Lisette.
Below is the complete, revised recommendation for the four features in Lisette. I’ve integrated your exact example for safe navigation and updated all sections for consistency, clarity, and alignment with Lisette’s current safety model (no
nil,Option<T>/Result<T, E>, exhaustivematch,?propagation, immutable defaults, and clean Go output).Description of the Four Additions
These four features create a powerful, cohesive upgrade that brings Lisette closer to F#’s expressive functional style (domain modeling, monadic workflows) while adding Dingo-style everyday ergonomics — all without compromising the strong safety guarantees in
safety.md(elimination ofnil, exhaustive matching, zero-cost abstractions, and safe Go interop).Units of Measure
Zero-runtime-cost numeric tags that prevent mixing incompatible values (e.g., USD vs BTC) at compile time.
Safe Navigation
?.and Coalescing??OperatorsConcise syntax for chaining
Option<T>accesses and providing defaults, dramatically reducing nestedmatchboilerplate.Computation Expressions
Builder blocks (
result { },option { },task { }) that allow linearlet!,do!,return, andreturn!syntax for monadic code.Active Patterns
User-defined named patterns that extend
matchwith reusable custom decomposition and validation logic.All features desugar cleanly to existing Lisette constructs or simple Go code, introduce no runtime overhead, and enhance the “make invalid states unrepresentable” philosophy from your safety documentation.
1. Units of Measure
Concrete Syntax Proposal:
Usage Examples:
Desugaring to Go:
Units are fully erased at compile time. All values become plain
float64/decimal(or equivalent) with type checking performed only by the Lisette compiler.Benefits for Lisette: Excellent for finance, crypto, scientific computing, or any domain with typed quantities. It pairs naturally with your enums and exhaustive matching to make currency or unit errors impossible at runtime.
2. Safe Navigation
?.and Coalescing??OperatorsConcrete Syntax Proposal:
Current style (already safe thanks to Option):
Additional Examples:
Desugaring (to current Lisette + Go):
The
?.operator desugars to nestedmatchonOption(or equivalentif letchains). The??operator becomes a fallback usingunwrap_or/unwrap_or_else.Final Go output is a clear series of
ifstatements with properOptionunwrapping, preserving full safety and readability.Benefits for Lisette: Your safety model already forces
Option<T>instead ofnil. This sugar makes deeply nestedOptioncode far more readable and concise while keeping every access explicitly safe and exhaustive. It brings Dingo-like ergonomics without weakening any guarantees fromsafety.md.3. Computation Expressions
Concrete Syntax Proposal:
Desugaring:
let! x = expr→ bind / map chain (leveraging your existing?where appropriate)return x→ wrap inOk/Some/ etc.return! expr→ direct return of the monadic valueDesugaring to Go (example for
result { }):The builder expands into explicit
if+matchorResulthandling chains, producing readable Go code similar to manual error checking but without duplication.Benefits for Lisette: Extends your
?operator into full, readable monadic workflows for error handling, validation, async, or tasks. Complex logic becomes linear and F#-like while desugaring to efficient, safe Go.4. Active Patterns
Concrete Syntax Proposal:
Usage:
Desugaring:
Active patterns compile to helper functions. The
matchexpression is rewritten to call these functions and then match on their returned value (Optionfor partial patterns or a simple variant for full ones). Exhaustiveness checking remains fully enforced.Benefits for Lisette: Extends your excellent pattern-matching infrastructure (
08-pattern-matching.md) with reusable, domain-specific logic (e.g., currency validation, parsing rules). Code stays expressive, safe, and exhaustive.Summary & Suggested Implementation Order
?./??– Quick, high-visibility ergonomics win that directly improves everydayOptionusage.match.?and builders.Together, these features make Lisette feel like a modern fusion of F# expressiveness and Dingo convenience while staying true to its Rust-inspired safety and Go compilation target. They require mostly parser, type-checker, and desugaring work — no changes to the runtime or Go output semantics.
Beta Was this translation helpful? Give feedback.
All reactions