use crate::functor::kind as functor_kind;
use crate::kind_based::kind::{Kind, Kind1};
use crate::monoid::Monoid;
use crate::transformers::except::kind::{ExceptT, ExceptTKind};
use crate::transformers::reader::kind::{ReaderT, ReaderTKind};
use crate::transformers::state::kind::{StateT, StateTKind};
use crate::transformers::writer::kind::{WriterT, WriterTKind};
pub trait MonadTrans<A, MKind: Kind1>: Kind {
#[must_use]
fn lift(inner: MKind::Of<A>) -> Self::Of<A>;
}
impl<R, MKind, A> MonadTrans<A, MKind> for ReaderTKind<R, MKind>
where
R: 'static,
A: 'static,
MKind: Kind1 + 'static,
MKind::Of<A>: Clone + 'static,
{
fn lift(inner: MKind::Of<A>) -> ReaderT<R, MKind, A> {
ReaderT::new(move |_r: R| inner.clone())
}
}
impl<S, MKind, A> MonadTrans<A, MKind> for StateTKind<S, MKind>
where
S: Clone + 'static,
A: 'static,
MKind: functor_kind::Functor<A, (A, S)> + Kind1 + 'static,
MKind::Of<A>: Clone + 'static,
MKind::Of<(A, S)>: 'static,
{
fn lift(inner: MKind::Of<A>) -> StateT<S, MKind, A> {
StateT::new(move |s: S| {
<MKind as functor_kind::Functor<A, (A, S)>>::map(inner.clone(), move |a| (a, s.clone()))
})
}
}
impl<W, MKind, A> MonadTrans<A, MKind> for WriterTKind<W, MKind>
where
W: Monoid + 'static,
A: 'static,
MKind: functor_kind::Functor<A, (A, W)> + Kind1 + 'static,
MKind::Of<A>: 'static,
MKind::Of<(A, W)>: 'static,
{
fn lift(inner: MKind::Of<A>) -> WriterT<W, MKind, A> {
let paired: MKind::Of<(A, W)> =
<MKind as functor_kind::Functor<A, (A, W)>>::map(inner, move |a| (a, W::empty()));
WriterT::new(paired)
}
}
impl<E, MKind, A> MonadTrans<A, MKind> for ExceptTKind<E, MKind>
where
E: 'static,
A: 'static,
MKind: functor_kind::Functor<A, Result<A, E>> + Kind1 + 'static,
MKind::Of<A>: 'static,
MKind::Of<Result<A, E>>: 'static,
{
fn lift(inner: MKind::Of<A>) -> ExceptT<E, MKind, A> {
let wrapped: MKind::Of<Result<A, E>> =
<MKind as functor_kind::Functor<A, Result<A, E>>>::map(inner, Ok);
ExceptT::new(wrapped)
}
}
impl<R, MKind: Kind1> ReaderTKind<R, MKind> {
#[must_use]
pub fn lift<A>(inner: MKind::Of<A>) -> ReaderT<R, MKind, A>
where
R: 'static,
A: 'static,
MKind: 'static,
MKind::Of<A>: Clone + 'static,
{
<Self as MonadTrans<A, MKind>>::lift(inner)
}
}
impl<S, MKind: Kind1> StateTKind<S, MKind> {
#[must_use]
pub fn lift<A>(inner: MKind::Of<A>) -> StateT<S, MKind, A>
where
S: Clone + 'static,
A: 'static,
MKind: functor_kind::Functor<A, (A, S)> + 'static,
MKind::Of<A>: Clone + 'static,
MKind::Of<(A, S)>: 'static,
{
<Self as MonadTrans<A, MKind>>::lift(inner)
}
}
impl<W, MKind: Kind1> WriterTKind<W, MKind> {
#[must_use]
pub fn lift<A>(inner: MKind::Of<A>) -> WriterT<W, MKind, A>
where
W: Monoid + 'static,
A: 'static,
MKind: functor_kind::Functor<A, (A, W)> + 'static,
MKind::Of<A>: 'static,
MKind::Of<(A, W)>: 'static,
{
<Self as MonadTrans<A, MKind>>::lift(inner)
}
}
impl<E, MKind: Kind1> ExceptTKind<E, MKind> {
#[must_use]
pub fn lift<A>(inner: MKind::Of<A>) -> ExceptT<E, MKind, A>
where
E: 'static,
A: 'static,
MKind: functor_kind::Functor<A, Result<A, E>> + 'static,
MKind::Of<A>: 'static,
MKind::Of<Result<A, E>>: 'static,
{
<Self as MonadTrans<A, MKind>>::lift(inner)
}
}