Skip to content

Instantly share code, notes, and snippets.

@nybble41
Created November 6, 2021 01:55
Show Gist options
  • Save nybble41/fcc3955507cbb5f4f9fe582c1f3329b7 to your computer and use it in GitHub Desktop.
Save nybble41/fcc3955507cbb5f4f9fe582c1f3329b7 to your computer and use it in GitHub Desktop.
#![feature(unboxed_closures)]
#![feature(fn_traits)]
pub mod hlist {
mod private {
pub trait Sealed {}
}
pub trait HList: private::Sealed {}
pub struct HNil;
pub struct HCons<T, R: HList>(pub T, pub R);
impl HList for HNil {}
impl<T, R: HList> HList for HCons<T, R> {}
impl private::Sealed for HNil {}
impl<T, R: HList> private::Sealed for HCons<T, R> {}
}
use hlist::{HList, HCons, HNil};
trait ComposableHList<'i, I: 'i>: HList where Self::Output: 'i {
type Output;
fn compose(self) -> Box<dyn Fn(I) -> Self::Output + 'i>;
}
impl<'i, I: 'i> ComposableHList<'i, I> for HNil {
type Output = I;
fn compose(self) -> Box<dyn Fn(I) -> Self::Output> {
Box::new(|i| i)
}
}
impl<'i, I: 'i, O: 'i, R: ComposableHList<'i, I>> ComposableHList<'i, I> for HCons<Box<dyn Fn<(R::Output,), Output = O>>, R> {
type Output = O;
fn compose(self) -> Box<dyn Fn(I) -> Self::Output + 'i> {
let HCons(f, r) = self;
let r: Box<dyn Fn(I) -> R::Output> = r.compose();
Box::new(move |i| { f(r(i)) })
}
}
fn compose<'i, I: 'i, O: 'i, L: ComposableHList<'i, I, Output = O>>(l: L) -> Box<dyn Fn(I) -> O + 'i> {
l.compose()
}
fn test1()
{
let atoi: Box<dyn Fn(Box<str>) -> isize> = Box::new(|s| s.parse().unwrap());
let add_one: Box<dyn Fn(isize) -> isize> = Box::new(|i| i + 1);
let square: Box<dyn Fn(isize) -> isize> = Box::new(|i| i * i);
let unsigned: Box<dyn Fn(isize) -> usize> = Box::new(|i| i as usize);
let test: Box<dyn Fn(Box<str>) -> usize> = compose(HCons(unsigned, HCons(square, HCons(add_one, HCons(atoi, HNil)))));
println!("{}", test(Box::from("3")));
}
fn test2()
{
let atoi: Box<dyn Fn(Box<str>) -> isize> = Box::new(|s| s.parse().unwrap());
let unsigned: Box<dyn Fn(isize) -> usize> = Box::new(|i| i as usize);
let test: Box<dyn Fn(Box<str>) -> usize> = compose(HCons(unsigned, HCons(atoi, HNil)));
println!("{}", test(Box::from("3")));
}
fn test3()
{
let unsigned: Box<dyn Fn(isize) -> usize> = Box::new(|i| i as usize);
let test: Box<dyn Fn(isize) -> usize> = compose(HCons(unsigned, HNil));
println!("{}", test(123));
}
fn main() {
test1();
test2();
test3();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment