Last active
July 7, 2022 03:47
-
-
Save Dessix/43460ba941a8ce81cfac93af97e4439a to your computer and use it in GitHub Desktop.
Rust Dependency Extraction (Not working, requires HRTB)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use frunk::{hlist::Selector, indices::Here}; | |
trait Has<A> { | |
fn get(&self) -> &A; | |
} | |
impl<A, S> Has<A> for S | |
where | |
S: Selector<A, Here>, | |
{ | |
fn get(&self) -> &A { | |
<S as Selector<A, Here>>::get(&self) | |
} | |
} | |
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | |
enum Outcome { | |
Good, | |
Bad, | |
} | |
trait Extract<'a, Deps> { | |
fn extract(&'a self) -> Deps; | |
} | |
trait Run<'a, Ext, Deps> { | |
fn run(&'a self, ext: &'a Ext) -> Outcome; | |
} | |
impl<'a, Ext> Extract<'a, ()> for Ext { | |
fn extract(&'a self) -> () { | |
() | |
} | |
} | |
impl<'a, Ext: 'a, T, R> Extract<'a, (&'a T, R)> for Ext | |
where | |
Ext: Has<T> + Extract<'a, R>, | |
{ | |
fn extract(&'a self) -> (&'a T, R) { | |
(self.get(), <Ext as Extract<'a, R>>::extract(self)) | |
} | |
} | |
impl<'a, Ext: 'a, D, F> Run<'a, Ext, D> for F | |
where | |
Ext: Extract<'a, D>, | |
F: Fn(D) -> Outcome, | |
{ | |
fn run(&'a self, exts: &'a Ext) -> Outcome { | |
self(<Ext as Extract<'a, D>>::extract(&exts)) | |
} | |
} | |
fn my_simple_handler(req: (&u16, ())) -> Outcome { | |
let (a, ()) = req; | |
if *a == 42 { | |
Outcome::Good | |
} else { | |
Outcome::Bad | |
} | |
} | |
fn my_handler(req: (&u8, (&u32, (&u16, ())))) -> Outcome { | |
let (a, (b, (c, ()))) = req; | |
println!("{} {} {}", a, b, c); | |
if *a as u32 + *b as u32 + *c as u32 == 42 { | |
Outcome::Good | |
} else { | |
Outcome::Bad | |
} | |
} | |
fn main() { | |
println!("Hello, world!"); | |
// Assert that unit extraction is valid | |
let _extract_unit: &dyn Extract<()> = &frunk::hlist![1u8, 2u32, 3u16]; | |
// Assert that singlet extraction is valid | |
// Note that this works at all because `Here` is used as the fixed index to Extract | |
// If we allowed type inference, this would theoretically work, but we'd have to supply | |
// a *set* of indecies, which must all be inferred in reverse. | |
// | |
// This would be trivially solved by value-HRTBs, if I am not mistaken, | |
// but these are currently unsupported by Rust. | |
let _extract_single: &dyn Extract<(&u8, ())> = &frunk::hlist![1u8]; | |
// Assert that an HList actually presents the given type | |
// This, again, works because `Here` is used, as above with `_extract_single`. | |
let outcome_simple = Run::run(&my_simple_handler, &frunk::hlist![1u16]); | |
// This would work if we could extract multiple but we need to deep-infer indecies | |
let outcome = Run::run(&my_handler, &frunk::hlist![1u8, 2u32, 3u16]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment