Created
January 4, 2023 13:10
-
-
Save oscartbeaumont/f6e7281cfb1257be2d9d7166bc5cf1cd to your computer and use it in GitHub Desktop.
pub trait Function {}
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
pub trait Function<TMarker> { | |
type Args; | |
type Result; | |
fn exec(&self, args: Self::Args) -> Self::Result; | |
} | |
// TODO: Duplicate all the impls for `FnOnce` and `FnMut` | |
// TODO: Support up to 12 args per functions. | |
pub enum TMarker {} | |
impl<R, TFunc: Fn() -> R> Function<TMarker> for TFunc { | |
type Args = (); | |
type Result = R; | |
fn exec(&self, _: Self::Args) -> Self::Result { | |
(self)() | |
} | |
} | |
impl<T, R, TFunc: Fn(T) -> R> Function<(T, R)> for TFunc { | |
type Args = T; | |
type Result = R; | |
fn exec(&self, args: Self::Args) -> Self::Result { | |
(self)(args) | |
} | |
} | |
impl<T, T1, R, TFunc: Fn(T, T1) -> R> Function<(T, T1, R)> for TFunc { | |
type Args = (T, T1); | |
type Result = R; | |
fn exec(&self, args: Self::Args) -> Self::Result { | |
(self)(args.0, args.1) | |
} | |
} | |
impl<T, T1, T2, R, TFunc: Fn(T, T1, T2) -> R> Function<(T, T1, T2, R)> for TFunc { | |
type Args = (T, T1, T2); | |
type Result = R; | |
fn exec(&self, args: Self::Args) -> Self::Result { | |
(self)(args.0, args.1, args.2) | |
} | |
} | |
fn joiner<A, TMarker1, B, TMarker2>( | |
a: A, | |
b: B, | |
) -> impl Function< | |
( | |
<A as Function<TMarker1>>::Args, | |
<B as Function<TMarker2>>::Result, | |
), | |
Args = <A as Function<TMarker1>>::Args, | |
Result = <B as Function<TMarker2>>::Result, | |
> | |
where | |
A: Function<TMarker1>, | |
B: Function<TMarker2, Args = A::Result>, | |
{ | |
move |args: A::Args| b.exec(a.exec(args)) | |
} | |
fn from_into_string(s: impl Into<String>) -> i32 { | |
s.into().parse::<i32>().unwrap() | |
} | |
pub trait SpecialType {} | |
#[derive(Clone)] | |
pub struct Demo; | |
impl SpecialType for Demo {} | |
fn only_special_types(_s: impl SpecialType) -> &'static str { | |
"my precious" | |
} | |
fn main() { | |
let a = |a: i32| a.to_string(); | |
let b = |a: String| a.parse::<i32>().unwrap(); | |
// i32 to String -> String to i32 | |
let c = joiner(a, b); | |
println!("{}", c.exec(42)); | |
// i32 to String -> `impl Into<String>` to i32 | |
let c = joiner(a, from_into_string); | |
println!("{}", c.exec(42)); | |
let a = Demo {}; // Will compile | |
// let a = "this is not the special type"; // Will not compile because it doesn't satisfy the trait bound on `only_special_types` | |
let c = joiner(move || a.clone(), only_special_types); | |
println!("{}", c.exec(())); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment