use super::functions::*;
use std::fmt;
#[allow(dead_code)]
pub struct ContM<R, A> {
pub(super) run_cont: Box<dyn FnOnce(Box<dyn FnOnce(A) -> R>) -> R>,
}
#[allow(dead_code)]
pub struct CodensityM<M, A> {
run_codensity: Box<dyn FnOnce(Box<dyn FnOnce(A) -> M>) -> M>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Maybe<A>(pub Option<A>);
impl<A> Maybe<A> {
pub fn just(a: A) -> Self {
Maybe(Some(a))
}
pub fn nothing() -> Self {
Maybe(None)
}
pub fn is_nothing(&self) -> bool {
self.0.is_none()
}
pub fn is_just(&self) -> bool {
self.0.is_some()
}
pub fn bind<B>(self, f: impl FnOnce(A) -> Maybe<B>) -> Maybe<B> {
match self.0 {
Some(a) => f(a),
None => Maybe(None),
}
}
pub fn fmap<B>(self, f: impl FnOnce(A) -> B) -> Maybe<B> {
Maybe(self.0.map(f))
}
pub fn into_option(self) -> Option<A> {
self.0
}
pub fn or_else(self, other: Maybe<A>) -> Maybe<A> {
if self.is_just() {
self
} else {
other
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Identity<A> {
pub value: A,
}
impl<A> Identity<A> {
pub fn pure(a: A) -> Self {
Identity { value: a }
}
pub fn bind<B>(self, f: impl FnOnce(A) -> Identity<B>) -> Identity<B> {
f(self.value)
}
pub fn map<B>(self, f: impl FnOnce(A) -> B) -> Identity<B> {
Identity {
value: f(self.value),
}
}
pub fn run(self) -> A {
self.value
}
}
#[allow(dead_code)]
pub enum FreeM<A> {
Pure(A),
Free(Box<FreeM<A>>),
}
pub struct Reader<R, A> {
run_fn: Box<dyn FnOnce(&R) -> A>,
}
impl<R: 'static, A: 'static> Reader<R, A> {
pub fn new(f: impl FnOnce(&R) -> A + 'static) -> Self {
Reader {
run_fn: Box::new(f),
}
}
pub fn pure(a: A) -> Self
where
A: Clone,
{
Reader::new(move |_| a.clone())
}
pub fn bind<B: 'static>(self, f: impl FnOnce(A) -> Reader<R, B> + 'static) -> Reader<R, B> {
Reader::new(move |r| {
let a = (self.run_fn)(r);
(f(a).run_fn)(r)
})
}
pub fn map<B: 'static>(self, f: impl FnOnce(A) -> B + 'static) -> Reader<R, B> {
Reader::new(move |r| f((self.run_fn)(r)))
}
pub fn run(self, env: &R) -> A {
(self.run_fn)(env)
}
pub fn ask() -> Reader<R, R>
where
R: Clone,
{
Reader::new(|r: &R| r.clone())
}
pub fn asks<B: 'static>(f: impl FnOnce(&R) -> B + 'static) -> Reader<R, B> {
Reader::new(f)
}
}
#[derive(Debug, Clone)]
pub struct Writer<W, A> {
pub value: A,
pub log: W,
}
impl<W: Default + Extend<W::Item>, A> Writer<W, A>
where
W: IntoIterator + Clone,
{
pub fn pure(a: A) -> Self
where
W: Default,
{
Writer {
value: a,
log: W::default(),
}
}
}
impl<A> Writer<Vec<String>, A> {
pub fn new(value: A, log: Vec<String>) -> Self {
Writer { value, log }
}
pub fn bind<B>(self, f: impl FnOnce(A) -> Writer<Vec<String>, B>) -> Writer<Vec<String>, B> {
let Writer {
value: a,
log: log1,
} = self;
let mut log1 = log1;
let Writer {
value: b,
log: log2,
} = f(a);
log1.extend(log2);
Writer {
value: b,
log: log1,
}
}
pub fn fmap<B>(self, f: impl FnOnce(A) -> B) -> Writer<Vec<String>, B> {
Writer {
value: f(self.value),
log: self.log,
}
}
pub fn tell(msg: String) -> Writer<Vec<String>, ()> {
Writer {
value: (),
log: vec![msg],
}
}
pub fn into_log(self) -> Vec<String> {
self.log
}
pub fn into_value(self) -> A {
self.value
}
}
#[allow(dead_code)]
pub struct IxState<I, J, A> {
pub(super) run_ix_state: Box<dyn FnOnce(I) -> (A, J)>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Either<E, A> {
inner: Result<A, E>,
}
impl<E, A> Either<E, A> {
pub fn right(a: A) -> Self {
Either { inner: Ok(a) }
}
pub fn left(e: E) -> Self {
Either { inner: Err(e) }
}
pub fn is_right(&self) -> bool {
self.inner.is_ok()
}
pub fn is_left(&self) -> bool {
self.inner.is_err()
}
pub fn bind<B>(self, f: impl FnOnce(A) -> Either<E, B>) -> Either<E, B> {
match self.inner {
Ok(a) => f(a),
Err(e) => Either::left(e),
}
}
pub fn fmap<B>(self, f: impl FnOnce(A) -> B) -> Either<E, B> {
Either {
inner: self.inner.map(f),
}
}
pub fn map_left<F2>(self, f: impl FnOnce(E) -> F2) -> Either<F2, A> {
Either {
inner: self.inner.map_err(f),
}
}
pub fn into_result(self) -> Result<A, E> {
self.inner
}
pub fn unwrap_right(self) -> A
where
E: std::fmt::Debug,
{
self.inner
.expect("Either::unwrap_right called on Left variant")
}
}
pub struct State<S, A> {
run_fn: Box<dyn FnOnce(S) -> (A, S)>,
}
impl<S: 'static, A: 'static> State<S, A> {
pub fn new(f: impl FnOnce(S) -> (A, S) + 'static) -> Self {
State {
run_fn: Box::new(f),
}
}
pub fn pure(a: A) -> Self
where
A: Clone,
{
State::new(move |s| (a.clone(), s))
}
pub fn bind<B: 'static>(self, f: impl FnOnce(A) -> State<S, B> + 'static) -> State<S, B> {
State::new(move |s| {
let (a, s2) = (self.run_fn)(s);
(f(a).run_fn)(s2)
})
}
pub fn map<B: 'static>(self, f: impl FnOnce(A) -> B + 'static) -> State<S, B> {
State::new(move |s| {
let (a, s2) = (self.run_fn)(s);
(f(a), s2)
})
}
pub fn run(self, initial: S) -> (A, S) {
(self.run_fn)(initial)
}
pub fn eval(self, initial: S) -> A {
self.run(initial).0
}
pub fn exec(self, initial: S) -> S {
self.run(initial).1
}
pub fn get() -> State<S, S>
where
S: Clone,
{
State::new(|s: S| {
let s2 = s.clone();
(s2, s)
})
}
pub fn put(new_s: S) -> State<S, ()>
where
S: 'static,
{
State::new(move |_| ((), new_s))
}
pub fn modify(f: impl FnOnce(S) -> S + 'static) -> State<S, ()> {
State::new(move |s| ((), f(s)))
}
}
#[allow(dead_code)]
pub struct ArrowF<A, B> {
pub(super) run_arrow: Box<dyn FnOnce(A) -> B>,
}