Hacker Newsnew | past | comments | ask | show | jobs | submit | maybevoid's commentslogin

The providers in CGP work a little different than implicit parameters in Scala. Specifically, the provider implementations are bound to a `Context` or `Self` type during compile-time wiring. So if you know the concrete `Context` type, then you can resolve all provider implementations for that context.

Because the wiring is done globally for an explicit `Context` type, there is no issue of ambiguity that arise based on when an implicit parameter is bound. I call this scoped coherence, as it leverages incoherence for overlappable implementations, but still maintain global coherence through the wiring in a context type.


Author here, glad to see this featured on HN! AMA about Context-Generic Programming or Rust traits!


Location: Leipzig, Germany

Remote: Yes

Willing to Relocate: No

Technologies: Rust, Haskell, Functional Programming, Programming Languages

Resume/CV: https://contextgeneric.dev/cv-soareschen-2025-07.pdf

Email: soares.chen@maybevoid.com

I am a software engineer with over 10 years of experience and a strong background in Rust, Haskell, and functional programming. I am seeking Rust-focused opportunities in areas such as AI, compilers, embedded systems, distributed systems, and operating systems. As the creator of Context-Generic Programming, I bring deep expertise in programming languages and a passion for applying that knowledge to tackle complex challenges with creative, effective solutions.

Read more about my profile at https://contextgeneric.dev/hire/.


With Context-Generic Programming (CGP), there is a way to get around the coherence restriction through a provider trait, and have overlapping implementations in safe, stable Rust. I have a proof of concept implementation of example in the article here: https://gist.github.com/soareschen/d37d74b26ecd0709517a80a3f...


For those who are new to the concept, in a nutshell, CGP allows you to bypass the coherence restrictions in traits/typeclasses, and define multiple overlapping and generic implementations for each CGP trait. As a consequence, when you define a new type, you need to specifically choose an implementation to be used with that type. This is called a wiring step, where you choose the provider implementations for your context.

On the surface, this addition doesn't seem significant. However, it opens up a world of possibilities for enabling powerful design patterns that are based on trait implementations that are named, generic, and overlappable. One of the greatest strengths of CGP is to enable safe, zero-cost, compile-time dispatching through the trait system to accomplish the things that in OOP would typically require dynamic dispatch with runtime errors.


For anyone interested in reading about CGP in Rust, here is the website:

https://contextgeneric.dev/

Just a FYI from their main page:

As of 2025, CGP remains in its early stages of development. While promising, it still has several rough edges, particularly in areas such as documentation, tooling, debugging techniques, community support, and ecosystem maturity.

...

At this stage, CGP is best suited for early adopters and potential contributors who are willing to experiment and help shape its future.


Clever work. I'm glad to see Rust is at the AbstractSingletonProxyFactoryBean stage of its lifecycle.

Look: patterns like this might unblock people locally but they point to a gap between what people want to say and what the base language allows them to express. In the long term, it's better to expand the language than devise increasingly heroic workarounds for syntactic sclerosis.


Hi everyone, I'm thrilled to share the third installment of my blog series on Extensible Data Types with CGP. In this post, I dive into the implementation details of the core traits in CGP that make extensible records possible, and explain how the extensible builder pattern is built on top of them.

If you're interested in the theory behind extensible data types, or curious about how CGP enables structural merging between two structs — as introduced in part one — this post is for you.


Hi everyone, I’m excited to share the latest progress in Context-Generic Programming (CGP), which now includes support for extensible records and variants in Rust.

For those of you coming from functional languages, this development effectively brings the power of datatype-generic programming, structural typing, row polymorphism and polymorphic variants to Rust. These are advanced type system features commonly found in languages like Haskell, PureScript and OCaml, and their availability in CGP represents a major leap in what is possible with the type system in Rust.

If you're new to the concept, extensible data types allow us to read from, construct, and extract data from a generic struct or enum without needing to know its concrete type definition. This opens the door to powerful design patterns, such as building generic builders or visitors that can operate flexibly over a wide range of data structures.

In the first post of this new blog series, I walk through a simple example that shows how to use extensible builders to construct an application context in a modular way.

I’d love to hear what you think — especially whether the approach feels practical or insightful for your own work. I’ll be sharing more updates over the next few days, so stay tuned!


(Slightly hijacking this thread to share about my comment for the same post on Reddit [1])

It's great to see you exploring some foundational patterns that closely align with the principles behind my work on Context-Generic Programming (CGP).

The structure of your `BlanketAdapter` and `Adapter` traits bears a strong resemblance to the concepts of provider traits and consumer traits in CGP. In particular, your use of the `Target` type is conceptually similar to how the `CgpProvider` associated type is used within a CGP context.

To illustrate the connection, I’ve put together a CGP-based reimplementation of your example. You can see the full code below or check it out as a gist at [3].

I hope this example helps to demonstrate how CGP builds on the same design ideas but generalizes them further. With CGP, the pattern becomes applicable to any trait, and the macros helps reduce a significant amount of boilerplate.

There’s definitely room to refine the example further — for instance, by extracting `load_state` into a separate trait so it can be reused across different implementations. I decided not to go too far down that path here, just to keep the example focused and easier to follow.

[1] https://www.reddit.com/r/rust/comments/1lovjej/comment/n0qh0...

[2] https://contextgeneric.dev/

[3] https://gist.github.com/soareschen/5b520eac0e818058cedfa2fbe...


I really like this idea - I keep finding myself re-implementing something like it every time I hit the brick wall of blanket impls. I'll see if there's a good place to make use of it in some of my current work at Gel (mainly trying to develop an ergonomic system for building postgres-style wire messages right now).


Coincidentally, I released a DSL last week called Hypershell [1], a Rust-based domain-specific language for shell scripting at the type level. While writing the blog post, I found myself wondering: will this kind of DSL be easier for LLMs to use than for humans?

In an initial experiment, I found that LLMs could translate familiar shell scripting concepts into Hypershell syntax reasonably well. More interestingly, they were able to fix common issues like type mismatches, especially when given light guidance or examples. That’s a big deal, because, like many embedded DSLs, Hypershell produces verbose and noisy compiler errors. Surprisingly, the LLM could often identify the underlying cause hidden in that mess and make the right correction.

This opens up a compelling possibility: LLMs could help bridge the usability gap that often prevents embedded DSLs from being more widely adopted. Debuggability is often the Achilles' heel of such languages, and LLMs seem capable of mitigating that, at least in simple cases.

More broadly, I think DSLs are poised to play a much larger role in AI-assisted development. They can be designed to sit closer to natural language while retaining strong domain-specific semantics. And LLMs appear to pick them up quickly, as long as they're given the right examples or docs to work with.

[1] https://contextgeneric.dev/blog/hypershell-release/


Your experience with Hypershell points to an interesting possibility: LLMs as DSL translators rather than replacements. This could actually democratize DSLs by lowering the learning curve while preserving their domain-specific benefits. The real opportunity might be DSLs optimized for both human semantics and machine translation.


Hello everyone!

I'm excited to share Hypershell, a modular, type-level DSL for writing shell-script-like programs directly in Rust! It's powered by Context-Generic Programming (CGP), which enables unprecedented modularity and extensibility, allowing you to easily extend or modify the language syntax and semantics.

I created Hypershell as a response to previous community feedback on CGP, seeking more practical application examples. Hypershell serves as a proof of concept, demonstrating how CGP can build highly modular DSLs — not just for shell-scripting, but also for areas like HTML or parsing. While it's an experimental project, shell-scripting was chosen as a fun and approachable example for all programmers. The blog post covers features like variable parameters, streaming I/O, native HTTP requests, and JSON encoding/decoding within your shell pipelines

A core innovation behind this is CGP's ability to bypass Rust's trait coherence restrictions, allowing for powerful dependency injection and eliminating tight coupling between implementations and concrete types. This means you can customize and extend Hypershell in ways that are typically very challenging in Rust.

Please feel free to share your thoughts and feedback on the project. I'm here to answer any questions!


Shameless plug: I am working on a solution in Rust that solves the coherence problems discussed in this post. I call it Context-Generic Programming (CGP), which makes it possible to write modular code that is generic over a context (Self) type without the coherence restrictions.

The basic idea of CGP is pretty simple: we introduce a companion provider trait that has an additional generic parameter that is placed at the "Self" position of the trait, and define a unique provider type that identifies each of the generic implementation. CGP then makes use of blanket implementations and macros to enable wiring of generic providers to a concrete context to implement the original trait, which we now call a consumer trait.

You can read about the full details of CGP at https://contextgeneric.dev/. I am also writing a book for CGP at https://patterns.contextgeneric.dev/, which goes more into details on how it works behind the scene.

Currently, I am preparing for a new v0.4.0 release of CGP, which includes a lot of quality of life improvements, including significantly improved error messages. I will also write a follow up blog post to specifically address how CGP can be used to solve the coherence problems stated in this post. So do stay tuned for more updates on CGP!


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: