trait Kind<T> { type Make; } enum OptionKind {} impl<T> Kind<T> for OptionKind { type Make = Option<T>; } trait FunctorKind<A, B>: Kind<A> + Kind<B> { fn fmapk(<Self as Kind<A>>::Make, impl Fn(A) -> B) -> <Self as Kind<B>>::Make; } impl<A, B> FunctorKind<A, B> for OptionKind { fn fmapk(me: Option<A>, f: impl Fn(A) -> B) -> Option<B> { match me { Some(m) => Some(f(m)), None => None, } } } trait Functor<A, B>: Sized { type Kind: FunctorKind<A, B>; //type Item; fn fmap(my: <Self::Kind as Kind<A>>::Make, f: impl Fn(A) -> B) -> <Self::Kind as Kind<B>>::Make { Self::Kind::fmapk(my, f) } } impl<A, B> Functor<A, B> for Option<A> { type Kind = OptionKind; } fn main() { println!("{:?}", OptionKind::fmapk(Some(10), |a| a + 1)); println!("{:?}", Option::fmap(Some(10), |a| a + 1)); }