h2s_core 0.18.0

A core part of h2s
Documentation
use crate::functor::{ExactlyOne, Functor};
use std::fmt::{Debug, Display};

pub trait FunctorWithContext: Functor {
    type Context: Context;

    fn fmap_with_context<A, B, F>(a: Self::Structure<A>, f: F) -> Self::Structure<B>
    where
        F: Fn(Self::Context, A) -> B;
}

impl<T> FunctorWithContext for ExactlyOne<T> {
    type Context = NoContext;

    fn fmap_with_context<A, B, F>(a: Self::Structure<A>, f: F) -> Self::Structure<B>
    where
        F: Fn(Self::Context, A) -> B,
    {
        Self::fmap(a, |a| f(NoContext, a))
    }
}

impl<T> FunctorWithContext for Option<T> {
    type Context = NoContext;

    fn fmap_with_context<A, B, F>(a: Self::Structure<A>, f: F) -> Self::Structure<B>
    where
        F: Fn(Self::Context, A) -> B,
    {
        Self::fmap(a, |a| f(NoContext, a))
    }
}

impl<T> FunctorWithContext for Vec<T> {
    type Context = ListIndex;

    fn fmap_with_context<A, B, F>(a: Self::Structure<A>, f: F) -> Self::Structure<B>
    where
        F: Fn(Self::Context, A) -> B,
    {
        Self::fmap(a.into_iter().enumerate().collect(), |(i, v)| {
            f(ListIndex(i), v)
        })
    }
}

impl<T, const M: usize> FunctorWithContext for [T; M] {
    type Context = ListIndex;

    fn fmap_with_context<A, B, F>(a: Self::Structure<A>, f: F) -> Self::Structure<B>
    where
        F: Fn(Self::Context, A) -> B,
    {
        // TODO fix inefficient conversion
        Self::fmap(
            a.into_iter()
                .enumerate()
                .collect::<Vec<_>>()
                .try_into()
                .map_err(|_| "")
                .unwrap(), // never failed
            |(i, v)| f(ListIndex(i), v),
        )
    }
}

pub trait Context: Debug + Display {}

#[derive(Debug)]
pub struct NoContext;

impl Context for NoContext {}

#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct ListIndex(pub usize);

impl Context for ListIndex {}