Skip to main content

oxilean_std/monad/
types.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use super::functions::*;
6use std::fmt;
7
8/// Continuation monad: ContM r a = (a -> r) -> r
9#[allow(dead_code)]
10pub struct ContM<R, A> {
11    pub(super) run_cont: Box<dyn FnOnce(Box<dyn FnOnce(A) -> R>) -> R>,
12}
13/// Codensity monad: CPS-transformed monad for efficiency.
14/// Codensity m a = forall r. (a -> m r) -> m r
15#[allow(dead_code)]
16pub struct CodensityM<M, A> {
17    run_codensity: Box<dyn FnOnce(Box<dyn FnOnce(A) -> M>) -> M>,
18}
19/// A simple `Maybe` monad (equivalent to `Option`).
20#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct Maybe<A>(pub Option<A>);
22impl<A> Maybe<A> {
23    /// Wrap a value as `Just a`.
24    pub fn just(a: A) -> Self {
25        Maybe(Some(a))
26    }
27    /// The `Nothing` constructor.
28    pub fn nothing() -> Self {
29        Maybe(None)
30    }
31    /// Return true if this is `Nothing`.
32    pub fn is_nothing(&self) -> bool {
33        self.0.is_none()
34    }
35    /// Return true if this is `Just _`.
36    pub fn is_just(&self) -> bool {
37        self.0.is_some()
38    }
39    /// Monadic bind.
40    pub fn bind<B>(self, f: impl FnOnce(A) -> Maybe<B>) -> Maybe<B> {
41        match self.0 {
42            Some(a) => f(a),
43            None => Maybe(None),
44        }
45    }
46    /// Functor map.
47    pub fn fmap<B>(self, f: impl FnOnce(A) -> B) -> Maybe<B> {
48        Maybe(self.0.map(f))
49    }
50    /// Return the inner `Option`.
51    pub fn into_option(self) -> Option<A> {
52        self.0
53    }
54    /// Alternative: use `other` if `self` is `Nothing`.
55    pub fn or_else(self, other: Maybe<A>) -> Maybe<A> {
56        if self.is_just() {
57            self
58        } else {
59            other
60        }
61    }
62}
63/// A simple identity monad: wraps a value with no effects.
64#[derive(Debug, Clone, PartialEq, Eq)]
65pub struct Identity<A> {
66    /// The wrapped value.
67    pub value: A,
68}
69impl<A> Identity<A> {
70    /// Wrap a value.
71    pub fn pure(a: A) -> Self {
72        Identity { value: a }
73    }
74    /// Bind: apply a function to the contained value.
75    pub fn bind<B>(self, f: impl FnOnce(A) -> Identity<B>) -> Identity<B> {
76        f(self.value)
77    }
78    /// Map: apply a function to the contained value.
79    pub fn map<B>(self, f: impl FnOnce(A) -> B) -> Identity<B> {
80        Identity {
81            value: f(self.value),
82        }
83    }
84    /// Extract the value.
85    pub fn run(self) -> A {
86        self.value
87    }
88}
89/// Free monad: Free f a = Pure a | Free (f (Free f a))
90/// Represents computations as data for interpretation.
91#[allow(dead_code)]
92pub enum FreeM<A> {
93    /// Pure value in the free monad.
94    Pure(A),
95    /// Suspended computation wrapped in an effect layer.
96    Free(Box<FreeM<A>>),
97}
98/// A `Reader` monad: computation depending on a shared environment `R`.
99pub struct Reader<R, A> {
100    run_fn: Box<dyn FnOnce(&R) -> A>,
101}
102impl<R: 'static, A: 'static> Reader<R, A> {
103    /// Create a `Reader` from a function.
104    pub fn new(f: impl FnOnce(&R) -> A + 'static) -> Self {
105        Reader {
106            run_fn: Box::new(f),
107        }
108    }
109    /// Lift a pure value.
110    pub fn pure(a: A) -> Self
111    where
112        A: Clone,
113    {
114        Reader::new(move |_| a.clone())
115    }
116    /// Monadic bind.
117    pub fn bind<B: 'static>(self, f: impl FnOnce(A) -> Reader<R, B> + 'static) -> Reader<R, B> {
118        Reader::new(move |r| {
119            let a = (self.run_fn)(r);
120            (f(a).run_fn)(r)
121        })
122    }
123    /// Map over the result.
124    pub fn map<B: 'static>(self, f: impl FnOnce(A) -> B + 'static) -> Reader<R, B> {
125        Reader::new(move |r| f((self.run_fn)(r)))
126    }
127    /// Run the computation with an environment.
128    pub fn run(self, env: &R) -> A {
129        (self.run_fn)(env)
130    }
131    /// Ask for the full environment.
132    pub fn ask() -> Reader<R, R>
133    where
134        R: Clone,
135    {
136        Reader::new(|r: &R| r.clone())
137    }
138    /// Ask for a projection of the environment.
139    pub fn asks<B: 'static>(f: impl FnOnce(&R) -> B + 'static) -> Reader<R, B> {
140        Reader::new(f)
141    }
142}
143/// A `Writer` monad: accumulates a log alongside a value.
144#[derive(Debug, Clone)]
145pub struct Writer<W, A> {
146    /// The produced value.
147    pub value: A,
148    /// The accumulated log.
149    pub log: W,
150}
151impl<W: Default + Extend<W::Item>, A> Writer<W, A>
152where
153    W: IntoIterator + Clone,
154{
155    /// Lift a pure value with an empty log.
156    pub fn pure(a: A) -> Self
157    where
158        W: Default,
159    {
160        Writer {
161            value: a,
162            log: W::default(),
163        }
164    }
165}
166impl<A> Writer<Vec<String>, A> {
167    /// Create a writer with a value and initial log entries.
168    pub fn new(value: A, log: Vec<String>) -> Self {
169        Writer { value, log }
170    }
171    /// Monadic bind: combine logs.
172    pub fn bind<B>(self, f: impl FnOnce(A) -> Writer<Vec<String>, B>) -> Writer<Vec<String>, B> {
173        let Writer {
174            value: a,
175            log: log1,
176        } = self;
177        let mut log1 = log1;
178        let Writer {
179            value: b,
180            log: log2,
181        } = f(a);
182        log1.extend(log2);
183        Writer {
184            value: b,
185            log: log1,
186        }
187    }
188    /// Map over the value.
189    pub fn fmap<B>(self, f: impl FnOnce(A) -> B) -> Writer<Vec<String>, B> {
190        Writer {
191            value: f(self.value),
192            log: self.log,
193        }
194    }
195    /// Emit a single log message.
196    pub fn tell(msg: String) -> Writer<Vec<String>, ()> {
197        Writer {
198            value: (),
199            log: vec![msg],
200        }
201    }
202    /// Return only the log.
203    pub fn into_log(self) -> Vec<String> {
204        self.log
205    }
206    /// Return only the value.
207    pub fn into_value(self) -> A {
208        self.value
209    }
210}
211/// Indexed state monad: IxState i j a = i -> (a, j)
212/// Tracks index transition from i to j while producing a.
213#[allow(dead_code)]
214pub struct IxState<I, J, A> {
215    pub(super) run_ix_state: Box<dyn FnOnce(I) -> (A, J)>,
216}
217/// A simple `Either` monad with error type `E`.
218#[derive(Debug, Clone, PartialEq, Eq)]
219pub struct Either<E, A> {
220    inner: Result<A, E>,
221}
222impl<E, A> Either<E, A> {
223    /// Construct a `Right a` (success).
224    pub fn right(a: A) -> Self {
225        Either { inner: Ok(a) }
226    }
227    /// Construct a `Left e` (error).
228    pub fn left(e: E) -> Self {
229        Either { inner: Err(e) }
230    }
231    /// Return true if `Right`.
232    pub fn is_right(&self) -> bool {
233        self.inner.is_ok()
234    }
235    /// Return true if `Left`.
236    pub fn is_left(&self) -> bool {
237        self.inner.is_err()
238    }
239    /// Monadic bind on the `Right` side.
240    pub fn bind<B>(self, f: impl FnOnce(A) -> Either<E, B>) -> Either<E, B> {
241        match self.inner {
242            Ok(a) => f(a),
243            Err(e) => Either::left(e),
244        }
245    }
246    /// Map over the `Right` side.
247    pub fn fmap<B>(self, f: impl FnOnce(A) -> B) -> Either<E, B> {
248        Either {
249            inner: self.inner.map(f),
250        }
251    }
252    /// Map over the `Left` side.
253    pub fn map_left<F2>(self, f: impl FnOnce(E) -> F2) -> Either<F2, A> {
254        Either {
255            inner: self.inner.map_err(f),
256        }
257    }
258    /// Convert to `Result`.
259    pub fn into_result(self) -> Result<A, E> {
260        self.inner
261    }
262    /// Extract the right value or panic.
263    pub fn unwrap_right(self) -> A
264    where
265        E: std::fmt::Debug,
266    {
267        self.inner
268            .expect("Either::unwrap_right called on Left variant")
269    }
270}
271/// A `State` monad: transforms state `S` into `(A, S)`.
272pub struct State<S, A> {
273    run_fn: Box<dyn FnOnce(S) -> (A, S)>,
274}
275impl<S: 'static, A: 'static> State<S, A> {
276    /// Create a `State` from a state transformation function.
277    pub fn new(f: impl FnOnce(S) -> (A, S) + 'static) -> Self {
278        State {
279            run_fn: Box::new(f),
280        }
281    }
282    /// Lift a pure value into the `State` monad.
283    pub fn pure(a: A) -> Self
284    where
285        A: Clone,
286    {
287        State::new(move |s| (a.clone(), s))
288    }
289    /// Monadic bind.
290    pub fn bind<B: 'static>(self, f: impl FnOnce(A) -> State<S, B> + 'static) -> State<S, B> {
291        State::new(move |s| {
292            let (a, s2) = (self.run_fn)(s);
293            (f(a).run_fn)(s2)
294        })
295    }
296    /// Map over the result value.
297    pub fn map<B: 'static>(self, f: impl FnOnce(A) -> B + 'static) -> State<S, B> {
298        State::new(move |s| {
299            let (a, s2) = (self.run_fn)(s);
300            (f(a), s2)
301        })
302    }
303    /// Run the state computation with an initial state.
304    pub fn run(self, initial: S) -> (A, S) {
305        (self.run_fn)(initial)
306    }
307    /// Run and return only the value.
308    pub fn eval(self, initial: S) -> A {
309        self.run(initial).0
310    }
311    /// Run and return only the final state.
312    pub fn exec(self, initial: S) -> S {
313        self.run(initial).1
314    }
315    /// Read the current state.
316    pub fn get() -> State<S, S>
317    where
318        S: Clone,
319    {
320        State::new(|s: S| {
321            let s2 = s.clone();
322            (s2, s)
323        })
324    }
325    /// Set a new state.
326    pub fn put(new_s: S) -> State<S, ()>
327    where
328        S: 'static,
329    {
330        State::new(move |_| ((), new_s))
331    }
332    /// Modify the state with a function.
333    pub fn modify(f: impl FnOnce(S) -> S + 'static) -> State<S, ()> {
334        State::new(move |s| ((), f(s)))
335    }
336}
337/// Arrow abstraction generalizing functions with effects.
338/// arr :: (a -> b) -> f a b
339#[allow(dead_code)]
340pub struct ArrowF<A, B> {
341    pub(super) run_arrow: Box<dyn FnOnce(A) -> B>,
342}