func docs
This commit is contained in:
		
							parent
							
								
									4ad05fbe7c
								
							
						
					
					
						commit
						a5fef129fe
					
				
							
								
								
									
										70
									
								
								src/func.rs
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								src/func.rs
									
									
									
									
									
								
							| @ -1,3 +1,12 @@ | ||||
| //! Generic functional concepts implemented in Rust.
 | ||||
| //! Some choices are intentionally less generic due to specifics of the domain.
 | ||||
| //! That, for example, includes the almost exclusive focus on [`FnOnce`] category.
 | ||||
| //!
 | ||||
| //! Sources:
 | ||||
| //! * <https://hackage.haskell.org/package/base-4.18.0.0/docs/Data-Functor.html>
 | ||||
| //! * <https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Applicative.html>
 | ||||
| //! * <https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Monad.html>
 | ||||
| 
 | ||||
| pub mod classes; | ||||
| pub mod clone_func; | ||||
| pub mod copy_func; | ||||
| @ -7,13 +16,16 @@ pub mod test_suite; | ||||
| #[cfg(test)] | ||||
| pub mod tests; | ||||
| 
 | ||||
| /// Part of Haskell's `Functor f` responsible to use `f a`.
 | ||||
| ///
 | ||||
| /// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Data-Functor.html>
 | ||||
| pub trait WeakFunctor { | ||||
|     type F<'a, A: 'a>: 'a | ||||
|     where | ||||
|         Self: 'a; | ||||
| } | ||||
| 
 | ||||
| /// Rust-specific implementation of [Functor], respecting `move` semantics.
 | ||||
| /// Rust-specific implementation of [`Functor`], respecting `move` semantics.
 | ||||
| ///
 | ||||
| /// Cannot insantiate for e.g. multi-element collections:
 | ||||
| /// ```compile_fail
 | ||||
| @ -33,7 +45,7 @@ pub trait WeakFunctor { | ||||
| /// ```
 | ||||
| /// Why does it fail to compile? `.map` expects `FnMut` (or we can think of it being `Fn`, doesn't matter here). But what we provide it (`f`) is
 | ||||
| ///
 | ||||
| /// For Haskell-style Functors, use [clone_func::CloneFunctor] instead.
 | ||||
| /// For Haskell-style Functors, use [`clone_func::CloneFunctor`] instead.
 | ||||
| /// ```
 | ||||
| /// use radn_rs::func::clone_func::*;
 | ||||
| ///
 | ||||
| @ -52,12 +64,17 @@ pub trait WeakFunctor { | ||||
| ///     }
 | ||||
| /// }
 | ||||
| /// ```
 | ||||
| 
 | ||||
| ///
 | ||||
| /// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Data-Functor.html>
 | ||||
| pub trait Functor: WeakFunctor { | ||||
|     /// Equivalent or Haskell's `fmap`.
 | ||||
|     /// Due to Rust limitations, it's not a `function->function` conversion.
 | ||||
|     /// For that see [`derivations::fmap`].
 | ||||
|     fn fmap<'a, A: 'a, B: 'a>(f: impl 'a + FnOnce(A) -> B, fa: Self::F<'a, A>) -> Self::F<'a, B> | ||||
|     where | ||||
|         Self: 'a; | ||||
| 
 | ||||
|     /// Equivalent of Haskell's `$>`/`<$`.
 | ||||
|     fn replace<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, b: B) -> Self::F<'a, B> | ||||
|     where | ||||
|         Self: 'a, | ||||
| @ -65,6 +82,7 @@ pub trait Functor: WeakFunctor { | ||||
|         Self::fmap(|_| b, fa) | ||||
|     } | ||||
| 
 | ||||
|     /// Equivalent of Haskell's `void`.
 | ||||
|     fn void<'a, A: 'a>(fa: Self::F<'a, A>) -> Self::F<'a, ()> | ||||
|     where | ||||
|         Self: 'a, | ||||
| @ -73,13 +91,9 @@ pub trait Functor: WeakFunctor { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub fn fmap<'a, T: 'a + Functor, A: 'a, B: 'a>( | ||||
|     f: impl 'a + FnOnce(A) -> B, | ||||
| ) -> impl FnOnce(T::F<'a, A>) -> T::F<'a, B> { | ||||
|     move |fa| T::fmap(f, fa) | ||||
| } | ||||
| 
 | ||||
| /// Part of [`Applicative`] responsible for Haskell's sequential application `<*>`.
 | ||||
| pub trait ApplicativeSeq: Functor { | ||||
|     /// Equivalent of Haskell's `<*>`.
 | ||||
|     fn seq<'a, A: 'a, B: 'a>( | ||||
|         ff: Self::F<'a, impl 'a + FnOnce(A) -> B>, | ||||
|         fa: Self::F<'a, A>, | ||||
| @ -88,7 +102,9 @@ pub trait ApplicativeSeq: Functor { | ||||
|         Self: 'a; | ||||
| } | ||||
| 
 | ||||
| /// Part of [`Applicative`] responsible for Haskell's result combination `listA2`.
 | ||||
| pub trait ApplicativeLA2: Functor { | ||||
|     /// Equivalent of Haskell's `listA2`.
 | ||||
|     fn la2<'a, A: 'a, B: 'a, C: 'a>( | ||||
|         f: impl 'a + FnOnce(A, B) -> C, | ||||
|         fa: Self::F<'a, A>, | ||||
| @ -98,15 +114,23 @@ pub trait ApplicativeLA2: Functor { | ||||
|         Self: 'a; | ||||
| } | ||||
| 
 | ||||
| /// Part of [`Applicative`] responsible for Rust-style result combination, specifically for tuples.
 | ||||
| pub trait ApplicativeTuple: Functor { | ||||
|     /// Similar to Haskell's `listA2` but with [Iterator::collect]-ish semantics.
 | ||||
|     fn tuple<'a, A: 'a, B: 'a>(fab: (Self::F<'a, A>, Self::F<'a, B>)) -> Self::F<'a, (A, B)> | ||||
|     where | ||||
|         Self: 'a; | ||||
| } | ||||
| 
 | ||||
| /// Equivalent of Haskell's `Applicative`.
 | ||||
| /// Split into [`ApplicativeSeq`], [`ApplicativeLA2`] and [`ApplicativeTuple`] due to Rust limitations.
 | ||||
| ///
 | ||||
| /// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Applicative.html>
 | ||||
| pub trait Applicative: Functor + ApplicativeSeq + ApplicativeLA2 + ApplicativeTuple { | ||||
|     /// Equivalent of Haskell's `pure`/`return`.
 | ||||
|     fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A>; | ||||
| 
 | ||||
|     /// Equivalent of Haskell's `*>`/`>>`.
 | ||||
|     fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> | ||||
|     where | ||||
|         Self: 'a, | ||||
| @ -114,6 +138,7 @@ pub trait Applicative: Functor + ApplicativeSeq + ApplicativeLA2 + ApplicativeTu | ||||
|         Self::seq(Self::replace(fa, |b| b), fb) | ||||
|     } | ||||
| 
 | ||||
|     /// Equivalent of Haskell's `<*`.
 | ||||
|     fn discard_second<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> | ||||
|     where | ||||
|         Self: 'a, | ||||
| @ -122,7 +147,11 @@ pub trait Applicative: Functor + ApplicativeSeq + ApplicativeLA2 + ApplicativeTu | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Equivalent of Haskell's `Monad`.
 | ||||
| ///
 | ||||
| /// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Monad.html>
 | ||||
| pub trait Monad: Applicative { | ||||
|     /// Equivalent of Haskell's `>==`.
 | ||||
|     fn bind<'a, A: 'a, B: 'a>( | ||||
|         fa: Self::F<'a, A>, | ||||
|         f: impl 'a + FnOnce(A) -> Self::F<'a, B>, | ||||
| @ -130,6 +159,7 @@ pub trait Monad: Applicative { | ||||
|     where | ||||
|         Self: 'a; | ||||
| 
 | ||||
|     /// Equivalent of Haskell's `join`.
 | ||||
|     fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A> | ||||
|     where | ||||
|         Self::F<'a, A>: 'a, | ||||
| @ -139,12 +169,28 @@ pub trait Monad: Applicative { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Equivalent of Haskell's `MonadFail`.
 | ||||
| ///
 | ||||
| /// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Monad.html>
 | ||||
| pub trait MonadFail<E>: Monad { | ||||
|     fn fail<'a, A>(e: E) -> Self::F<'a, A>; | ||||
|     /// Equivalent of Haskell's `fail`.
 | ||||
|     fn fail<'a, A: 'a>(e: E) -> Self::F<'a, A> | ||||
|     where | ||||
|         Self: 'a; | ||||
| } | ||||
| 
 | ||||
| /// Equivalent of Haskell's `Alternative`.
 | ||||
| /// Lacks `some`/`many` definitions due to [`FnOnce`] category semantics.
 | ||||
| ///
 | ||||
| /// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Applicative.html>
 | ||||
| pub trait Alternative: Applicative { | ||||
|     fn empty<'a, A>() -> Self::F<'a, A>; | ||||
|     /// Equivalent of Haskell's `empty`.
 | ||||
|     fn empty<'a, A: 'a>() -> Self::F<'a, A> | ||||
|     where | ||||
|         Self: 'a; | ||||
| 
 | ||||
|     fn add<'a, A>(fa: Self::F<'a, A>, fb: Self::F<'a, A>) -> Self::F<'a, A>; | ||||
|     /// Equivalent of Haskell's `<|>`.
 | ||||
|     fn add<'a, A: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, A>) -> Self::F<'a, A> | ||||
|     where | ||||
|         Self: 'a; | ||||
| } | ||||
|  | ||||
| @ -1,3 +1,24 @@ | ||||
| //! Implementation of some basic classes (in Haskell's meaning of a class).
 | ||||
| //!
 | ||||
| //! To get an understanding of what classes are about, see [`option`].
 | ||||
| //!
 | ||||
| //! For [`MonadFail<E>`] examples, see [`result`][^research].
 | ||||
| //!
 | ||||
| //! For the simplest form (even ChatGPT can understand it! lol) of [`Monad`], see [`solo`][^production].
 | ||||
| //!
 | ||||
| //! For async support, see [`future`][^production][^research].
 | ||||
| //!
 | ||||
| //! For "creative" execution models, see [`lazy`][^research] and [`stackless`][^research].
 | ||||
| //!
 | ||||
| //! To see when not to use [Monad]s, see [`composition`][^research].
 | ||||
| //!
 | ||||
| //! [^production]: classes expected to be used in production.
 | ||||
| //!
 | ||||
| //! [^research]: classes used for research purposes to enhance the abstract interfaces.
 | ||||
| 
 | ||||
| #[cfg(doc)] | ||||
| use crate::func::*; | ||||
| 
 | ||||
| pub mod composition; | ||||
| pub mod future; | ||||
| pub mod lazy; | ||||
|  | ||||
| @ -1,3 +1,8 @@ | ||||
| //! Async [Monad] based on [`Pin<Box<dyn Future>>`] (see: [`Pin`], [`Box::pin`], [`Future`]).
 | ||||
| //! This generally allows just using `.await` on wrapped instances.
 | ||||
| //!
 | ||||
| //! For sync, see [`super::solo`].
 | ||||
| 
 | ||||
| use std::{future::Future, pin::Pin}; | ||||
| 
 | ||||
| use futures::join; | ||||
|  | ||||
| @ -1,6 +1,15 @@ | ||||
| //! Helper [Monad]s to defer execution until necessary.
 | ||||
| //! Wrapped value is just a box pointing to the constructor function.
 | ||||
| //!
 | ||||
| //! Due to semantical laziness,
 | ||||
| //! [`LazyClass::replace`] and [`LazyClass::discard_first`]/[`LazyClass::discard_second`]
 | ||||
| //! actually fully cancel the "unnecessary" computation.
 | ||||
| //!
 | ||||
| //! For stackless execution see [`super::stackless`].
 | ||||
| 
 | ||||
| use crate::func::*; | ||||
| 
 | ||||
| struct LazyClass; | ||||
| pub struct LazyClass; | ||||
| 
 | ||||
| impl WeakFunctor for LazyClass { | ||||
|     type F<'a, A: 'a> = Box<dyn 'a + FnOnce() -> A>; | ||||
|  | ||||
| @ -1,3 +1,12 @@ | ||||
| //! Implementation of [`Monad`] for [`Option<A>`].
 | ||||
| //!
 | ||||
| //! If any of the input values are [`None`], you can expect the output to be [`None`] as well.
 | ||||
| //! That includes
 | ||||
| //! [`OptionClass::replace`] and [`OptionClass::discard_first`]/[`OptionClass::discard_second`],
 | ||||
| //! even if the value of the option would be ignored.
 | ||||
| //!
 | ||||
| //! For [`Result<A, E>`] alternative see [`super::result`]
 | ||||
| 
 | ||||
| use crate::func::*; | ||||
| 
 | ||||
| pub struct OptionClass; | ||||
|  | ||||
| @ -1,3 +1,12 @@ | ||||
| //! Implementation of [`MonadFail<E>`] for [`Result<A, E>`].
 | ||||
| //!
 | ||||
| //! If any of the input values are [`Err`], you can expect the output to be [`Err`] as well.
 | ||||
| //! That includes
 | ||||
| //! [`ResultClass::replace`] and [`ResultClass::discard_first`]/[`ResultClass::discard_second`],
 | ||||
| //! even if the value of the option would be ignored.
 | ||||
| //!
 | ||||
| //! For [`Option<A>`] alternative see [`super::option`]
 | ||||
| 
 | ||||
| use crate::func::*; | ||||
| 
 | ||||
| pub struct ResultClass<E: 'static>(E); | ||||
| @ -72,3 +81,12 @@ impl<E> Monad for ResultClass<E> { | ||||
|         ffa? | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<E> MonadFail<E> for ResultClass<E> { | ||||
|     fn fail<'a, A: 'a>(e: E) -> Self::F<'a, A> | ||||
|     where | ||||
|         Self: 'a, | ||||
|     { | ||||
|         Err(e) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,3 +1,7 @@ | ||||
| //! Simplest sync [Monad].
 | ||||
| //!
 | ||||
| //! For async, see [`super::future`].
 | ||||
| 
 | ||||
| use crate::func::*; | ||||
| 
 | ||||
| pub struct SoloClass; | ||||
|  | ||||
| @ -1,3 +1,8 @@ | ||||
| //! Helper [Monad]s to move deep execution chains off the stack onto the heap.
 | ||||
| //! [`Stackless<A>`] represents a wrapped value.
 | ||||
| //!
 | ||||
| //! For lazy stackful execution see [`super::lazy`].
 | ||||
| 
 | ||||
| use std::{cell::Cell, rc::Rc}; | ||||
| 
 | ||||
| use crate::func::derivations::*; | ||||
| @ -50,7 +55,9 @@ impl<'a, A: 'a> Stackless<'a, A> { | ||||
|         self.0(Box::new(f)) | ||||
|     } | ||||
| 
 | ||||
|     fn bind<B: 'a>(self, f: impl 'a + FnOnce(A) -> Stackless<'a, B>) -> Stackless<'a, B> { | ||||
|     /// Method-like equivalent of [`Monad::bind`],
 | ||||
|     /// the preferred way to chain [`Stackless<A>`] and `FnOnce(A) -> Stackless<B>` into [`Stackless<B>`].
 | ||||
|     pub fn bind<B: 'a>(self, f: impl 'a + FnOnce(A) -> Stackless<'a, B>) -> Stackless<'a, B> { | ||||
|         Stackless(Box::new(|takesb| { | ||||
|             let lcell = Rc::new(Cell::new(None)); | ||||
|             let rcell = lcell.clone(); | ||||
| @ -66,7 +73,8 @@ impl<'a, A: 'a> Stackless<'a, A> { | ||||
|         })) | ||||
|     } | ||||
| 
 | ||||
|     fn map<B: 'a>(self, f: impl 'a + FnOnce(A) -> B) -> Stackless<'a, B> { | ||||
|     /// Method-like equivalent of [`Functor::fmap`].
 | ||||
|     pub fn map<B: 'a>(self, f: impl 'a + FnOnce(A) -> B) -> Stackless<'a, B> { | ||||
|         Stackless(Box::new(|takesb| { | ||||
|             let lcell = Rc::new(Cell::new(None)); | ||||
|             let rcell = lcell.clone(); | ||||
| @ -85,6 +93,8 @@ impl<'a, A: 'a> Stackless<'a, A> { | ||||
|         })) | ||||
|     } | ||||
| 
 | ||||
|     /// Evaluate. Process is loop-like on the inside
 | ||||
|     /// with the least amount of recursion the current model allows to use.
 | ||||
|     pub fn evaluate(self) -> A { | ||||
|         let ocell = Rc::new(Cell::new(None)); | ||||
|         let icell = ocell.clone(); | ||||
|  | ||||
| @ -1,3 +1,9 @@ | ||||
| //! Equivalent of [`crate::func`] for [`Clone`]/[`Fn`] Category.
 | ||||
| //! Similar to what you'd encounter in Haskell.
 | ||||
| //! Not well maintained due to not being used in the main RADN code base.
 | ||||
| //!
 | ||||
| //! See also: [`super::copy_func`]
 | ||||
| 
 | ||||
| pub trait CloneWeakFunctor { | ||||
|     type ClF<'a, A: Clone>: Clone; | ||||
| } | ||||
|  | ||||
| @ -1,3 +1,8 @@ | ||||
| //! Equivalent of [`crate::func`] for [`Copy`]/[`Fn`] Category.
 | ||||
| //! Not well maintained due to not being used in the main RADN code base.
 | ||||
| //!
 | ||||
| //! See also: [`super::clone_func`]
 | ||||
| 
 | ||||
| pub trait CopyWeakFunctor { | ||||
|     type CF<'a, A: Copy>: Copy; | ||||
| } | ||||
|  | ||||
| @ -1,5 +1,14 @@ | ||||
| //! Useful helper functions/methods to extrapolate the existing behaviour.
 | ||||
| 
 | ||||
| use crate::func::*; | ||||
| 
 | ||||
| /// Equivalent of Haskell's `fmap`. `function-function` equivalent of [Functor::fmap].
 | ||||
| pub fn fmap<'a, T: 'a + Functor, A: 'a, B: 'a>( | ||||
|     f: impl 'a + FnOnce(A) -> B, | ||||
| ) -> impl FnOnce(T::F<'a, A>) -> T::F<'a, B> { | ||||
|     move |fa| T::fmap(f, fa) | ||||
| } | ||||
| 
 | ||||
| pub trait ApplicativeLA2ViaSeq: ApplicativeSeq { | ||||
|     fn _la2_via_seq<'a, A: 'a, B: 'a, C: 'a>( | ||||
|         f: impl 'a + FnOnce(A, B) -> C, | ||||
|  | ||||
| @ -3,7 +3,8 @@ use super::{tests::*, *}; | ||||
| pub trait FunctorTestSuite: WeakFunctor + Eqr { | ||||
|     fn sample<'a, A: 'a, F: FnMut(&'a dyn Fn(A) -> Self::F<'a, A>)>(f: F) | ||||
|     where | ||||
|         Self::F<'a, A>: 'a, Self: 'a; | ||||
|         Self::F<'a, A>: 'a, | ||||
|         Self: 'a; | ||||
| } | ||||
| 
 | ||||
| pub fn functor_follows_laws<T: Functor + FunctorTestSuite>() -> R { | ||||
|  | ||||
| @ -5,14 +5,14 @@ use std::{error::Error, marker::PhantomData, rc::Rc}; | ||||
| 
 | ||||
| use crate::core::*; | ||||
| 
 | ||||
| /// This trait combines functionality of [Mentionable] and [Factory],
 | ||||
| /// while limiting [Mentionable::points] (and corresponding [Mentionable::topology]) to an empty sequence.
 | ||||
| /// This trait combines functionality of [`Mentionable`] and [`Factory`],
 | ||||
| /// while limiting [`Mentionable::points`] (and corresponding [`Mentionable::topology`]) to an empty sequence.
 | ||||
| pub trait Atomic: 'static + Sized + Clone + Serializable { | ||||
|     /// Equivalent of [Factory::ParseError].
 | ||||
|     /// Equivalent of [`Factory::ParseError`].
 | ||||
|     type ParseError: Error; | ||||
|     /// Static equivalent of [Factory::deserialize].
 | ||||
|     /// Static equivalent of [`Factory::deserialize`].
 | ||||
|     fn deserialize(deserializer: &mut dyn Deserializer) -> Result<Self, Self::ParseError>; | ||||
|     /// Static equivalent of [Factory::unexpected_tail].
 | ||||
|     /// Static equivalent of [`Factory::unexpected_tail`].
 | ||||
|     fn unexpected_tail(tail: &[u8]) -> Self::ParseError; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -0,0 +1 @@ | ||||
| 
 | ||||
| @ -1,4 +1,4 @@ | ||||
| //! This module introduces [Option]-like concepts into RADN typesystem using [Nullable].
 | ||||
| //! This module introduces [`Option`]-like concepts into RADN typesystem using [`Nullable`].
 | ||||
| 
 | ||||
| use crate::core::*; | ||||
| use crate::std::*; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user