#![allow(clippy::arithmetic_side_effects)]
use crate::prelude::*;
#[inline]
pub fn hash<H: core::hash::Hash>(h: H) -> u64 {
use core::hash::Hasher;
let mut hasher = ahash::AHasher::default();
h.hash(&mut hasher);
hasher.finish()
}
#[inline]
pub fn hash_consume<M: crate::monad::Monad<u64, Monad<u64> = M>, H: core::hash::Hash>(h: H) -> M {
consume(hash(h))
}
pub mod monad {
use crate::prelude::*;
#[inline]
pub fn left_identity<
A: Clone,
B,
MA: Monad<A> + core::ops::Shr<&'static F, Output = MA::Monad<B>>,
F: FnOnce(A) -> MA::Monad<B>,
>(
a: A,
f: &'static F,
) -> bool
where
MA::Monad<B>: PartialEq,
{
(MA::consume(a.clone()) >> f) == f(a)
}
#[inline]
#[allow(clippy::needless_pass_by_value)]
pub fn right_identity<A, MA: Monad<A, Monad<A> = MA> + Clone + PartialEq>(ma: MA) -> bool {
ma.clone().bind::<A, _>(consume) == ma
}
#[inline]
#[allow(clippy::trait_duplication_in_bounds)]
pub fn associativity<
A,
B,
C,
M: Monad<A, Monad<A> = M>
+ Clone
+ core::ops::Shr<&'static F, Output = M::Monad<B>>
+ core::ops::Shr<fn(A) -> M::Monad<C>, Output = M::Monad<C>>,
F: FnOnce(A) -> M::Monad<B>,
G: FnOnce(B) -> M::Monad<C>,
>(
m: M,
f: &'static F,
g: &'static G,
) -> bool
where
M::Monad<B>: core::ops::Shr<&'static G, Output = M::Monad<C>>,
M::Monad<C>: PartialEq,
{
#![allow(clippy::as_conversions)]
((m.clone() >> f) >> g) == m.bind::<C, _>(move |a| (f(a) >> g))
}
}
pub mod functor {
use crate::prelude::*;
#[inline]
pub fn identity<A, FA: Functor<A, Functor<A> = FA> + Clone + PartialEq>(fa: FA) -> bool {
fa.clone() == fa.fmap(core::convert::identity)
}
#[inline]
pub fn composition<A, B, C, FA: Functor<A> + Clone, G: FnOnce(A) -> B, F: FnOnce(B) -> C>(
fa: FA,
f: F,
g: G,
) -> bool
where
FA::Functor<C>: PartialEq<<FA::Functor<B> as Functor<B>>::Functor<C>>,
{
fa.clone().fmap(|x| f(g(x))) == fa.fmap(g).fmap(f)
}
}