Skip to content

Instantly share code, notes, and snippets.

@fero23
Last active February 10, 2021 15:45
Show Gist options
  • Save fero23/479f5ceaad4bfa43e64026f2ab402b35 to your computer and use it in GitHub Desktop.
Save fero23/479f5ceaad4bfa43e64026f2ab402b35 to your computer and use it in GitHub Desktop.
Another take on higher kinded types for Rust
trait HKT<N> {
type C;
type NC;
}
trait Functor<N>: HKT<N> {
fn fmap<F: Fn(&Self::C) -> N>(&self, f: F) -> Self::NC;
}
impl<C, N> HKT<N> for Option<C> {
type C = C;
type NC = Option<N>;
}
impl<T, N> Functor<N> for Option<T> {
fn fmap<F: Fn(&Self::C) -> N>(&self, f: F) -> Option<N> {
self.as_ref().map(f)
}
}
impl<C, N> HKT<N> for Vec<C> {
type C = C;
type NC = Vec<N>;
}
impl<T, N> Functor<N> for Vec<T> {
fn fmap<F: Fn(&Self::C) -> N>(&self, f: F) -> Vec<N> {
self.iter().map(|t| f(t)).collect()
}
}
#[derive(Debug)]
struct FunctorContainer<F>(F);
impl<N, F: Functor<N>> HKT<N> for FunctorContainer<F> {
type C = F::C;
type NC = FunctorContainer<F::NC>;
}
impl<N, FT: Functor<N>> Functor<N> for FunctorContainer<FT> {
fn fmap<F: Fn(&Self::C) -> N>(&self, f: F) -> Self::NC {
FunctorContainer(self.0.fmap(f))
}
}
fn main() {
let fc1 = FunctorContainer(Some(42));
let fc2 = FunctorContainer(vec![1,2,3,4,5]);
println!("{:?} {:?}",
fc1.fmap(|n| n.to_string()),
fc2.fmap(|n| n.to_string()));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment