#[cfg(all(not(feature = "std"), feature = "alloc"))]
use alloc::{boxed::Box, vec::Vec};
use core::marker::PhantomData;
pub trait HKT {
type Of<T>;
}
pub struct OptionF;
impl HKT for OptionF {
type Of<T> = Option<T>;
}
pub struct ResultF<E> {
_marker: PhantomData<E>,
}
impl<E> HKT for ResultF<E> {
type Of<T> = Result<T, E>;
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct VecF;
#[cfg(any(feature = "std", feature = "alloc"))]
impl HKT for VecF {
#[cfg(feature = "std")]
type Of<T> = Vec<T>;
#[cfg(all(not(feature = "std"), feature = "alloc"))]
type Of<T> = alloc::vec::Vec<T>;
}
pub trait HKT2 {
type P<A, B>;
}
pub struct ResultBF;
impl HKT2 for ResultBF {
type P<A, B> = Result<B, A>;
}
pub struct TupleF;
impl HKT2 for TupleF {
type P<A, B> = (A, B);
}
pub struct IdentityF;
impl HKT for IdentityF {
type Of<T> = T;
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NonEmptyVec<T> {
pub head: T,
pub tail: Vec<T>,
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T> NonEmptyVec<T> {
pub fn new(head: T, tail: Vec<T>) -> Self {
Self { head, tail }
}
pub fn singleton(value: T) -> Self {
Self {
head: value,
tail: Vec::new(),
}
}
pub fn len(&self) -> usize {
1 + self.tail.len()
}
pub fn is_empty(&self) -> bool {
false }
pub fn iter(&self) -> impl Iterator<Item = &T> {
core::iter::once(&self.head).chain(self.tail.iter())
}
pub fn tails(&self) -> NonEmptyVec<NonEmptyVec<T>>
where
T: Clone,
{
let mut result_tail = Vec::new();
for i in 1..self.len() {
result_tail.push(NonEmptyVec::new(
self.tail[i - 1].clone(),
self.tail[i..].to_vec(),
));
}
NonEmptyVec::new(self.clone(), result_tail)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct NonEmptyVecF;
#[cfg(any(feature = "std", feature = "alloc"))]
impl HKT for NonEmptyVecF {
type Of<T> = NonEmptyVec<T>;
}
pub struct EnvF<E>(PhantomData<E>);
impl<E> HKT for EnvF<E> {
type Of<T> = (E, T);
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct StoreF<S>(PhantomData<S>);
#[cfg(any(feature = "std", feature = "alloc"))]
impl<S: 'static> HKT for StoreF<S> {
type Of<T> = (Box<dyn Fn(S) -> T>, S);
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct TracedF<M>(PhantomData<M>);
#[cfg(any(feature = "std", feature = "alloc"))]
impl<M: 'static> HKT for TracedF<M> {
type Of<T> = Box<dyn Fn(M) -> T>;
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct ReaderF<E>(PhantomData<E>);
#[cfg(any(feature = "std", feature = "alloc"))]
impl<E: 'static> HKT for ReaderF<E> {
type Of<T> = Box<dyn Fn(E) -> T>;
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<E: Clone + 'static> ReaderF<E> {
pub fn fmap<A: 'static, B: 'static>(
fa: Box<dyn Fn(E) -> A>,
f: impl Fn(A) -> B + 'static,
) -> Box<dyn Fn(E) -> B> {
Box::new(move |e| f(fa(e)))
}
pub fn pure<A: Clone + 'static>(a: A) -> Box<dyn Fn(E) -> A> {
Box::new(move |_| a.clone())
}
pub fn chain<A: 'static, B: 'static>(
fa: Box<dyn Fn(E) -> A>,
f: impl Fn(A) -> Box<dyn Fn(E) -> B> + 'static,
) -> Box<dyn Fn(E) -> B> {
Box::new(move |e: E| {
let a = fa(e.clone());
f(a)(e)
})
}
pub fn ask() -> Box<dyn Fn(E) -> E> {
Box::new(|e| e)
}
pub fn local<A: 'static>(
f: impl Fn(E) -> E + 'static,
reader: Box<dyn Fn(E) -> A>,
) -> Box<dyn Fn(E) -> A> {
Box::new(move |e| reader(f(e)))
}
}