Skip to content

Instantly share code, notes, and snippets.

@AnthonyMikh
Last active October 29, 2021 23:09
Show Gist options
  • Save AnthonyMikh/f5b6beb3f5af0cc3ce9ada13c55754a6 to your computer and use it in GitHub Desktop.
Save AnthonyMikh/f5b6beb3f5af0cc3ce9ada13c55754a6 to your computer and use it in GitHub Desktop.
Illustration of composable parametrized behavior in Rust
trait Provide<Item, Path> {
fn provide(&mut self) -> Item;
}
struct Itself;
struct Head<T>(T);
struct Tail<T>(T);
struct HNil;
struct HCons<H, T>(H, T);
impl<Item, H, T, HSource> Provide<Item, Head<HSource>> for HCons<H, T>
where
H: Provide<Item, HSource>,
{
fn provide(&mut self) -> Item {
self.0.provide()
}
}
impl<Item, H, T, TSource> Provide<Item, Tail<TSource>> for HCons<H, T>
where
T: Provide<Item, TSource>,
{
fn provide(&mut self) -> Item {
self.1.provide()
}
}
trait ProvideExt<T> {
fn provide_via_path<P>(&mut self) -> T
where
Self: Provide<T, P>;
}
impl<Item, T> ProvideExt<Item> for T {
fn provide_via_path<P>(&mut self) -> Item
where
Self: Provide<Item, P>,
{
self.provide()
}
}
trait ProvideBase<Item> {
fn provide_base(&mut self) -> Item;
}
impl<Item, T> Provide<Item, Itself> for T
where
T: ProvideBase<Item>,
{
fn provide(&mut self) -> Item {
self.provide_base()
}
}
struct Cloning<T>(T);
impl<T> ProvideBase<T> for Cloning<T>
where
T: Clone,
{
fn provide_base(&mut self) -> T {
self.0.clone()
}
}
struct TheAnswer;
impl ProvideBase<u32> for TheAnswer {
fn provide_base(&mut self) -> u32 {
42
}
}
fn _test() {
let mut list = HCons(Cloning(0), HCons(Cloning(()), HNil));
let _: u32 = list.provide();
let _: () = list.provide();
let mut list = HCons(TheAnswer, HCons(Cloning(0), HNil));
let _ = list.provide_via_path::<Head<Itself>>();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment