diff options
| author | Andreas Grois <andi@grois.info> | 2023-03-23 00:00:08 +0100 |
|---|---|---|
| committer | Andreas Grois <andi@grois.info> | 2023-03-23 00:00:08 +0100 |
| commit | 1bdd780f02b5ba57795820360d19b241cb0dd006 (patch) | |
| tree | 0ae211f4eb65f0de671151b8284200116b141b90 | |
| parent | 206d8419e6f04146db7a49c79e0978ecfccea974 (diff) | |
Minor docs update and addition of one unit test.
| -rw-r--r-- | Cargo.toml | 9 | ||||
| -rw-r--r-- | src/lib.rs | 38 |
2 files changed, 41 insertions, 6 deletions
@@ -1,13 +1,14 @@ [package] name = "higher-free-macro" -version = "0.0.1" +version = "0.1.0" edition = "2021" -authors = ["Andreas Grois"] +authors = ["Andreas Grois", "stillalive studios"] rust-version = "1.66.1" -description = "A macro that allows to conjure a Free Monad for every Functor. This builds on the traits from the higher crate, and re-exports said crate." +description = "A macro that creates a (naive) Free Monad type based on a user-supplied Functor. It uses the traits from the \"higher\" crate. This macro is a port of the Control.Monad.Free part of the \"free\" Haskell package by Edward Kmett." repository = "https://github.com/soulsource/higher-free-macro" license = "MPL-2.0+" -keywords = ["functor", "applicative", "monad", "category-theory", "haskell"] +keywords = ["functor", "applicative", "monad", "category-theory", "haskell", "free-monad"] +categories = ["mathematics", "data-structures"] [dependencies] higher = "0.2"
\ No newline at end of file @@ -1,6 +1,6 @@ //! A macro that uses the traits from the [higher] crate and generates a Free [`Monad`][higher::Monad] type for a given [`Functor`][higher::Functor]. //! -//! This is a port of the ["free" Haskell package](https://hackage.haskell.org/package/free). +//! This is a port of the Control.Monad.Free part of the ["free" Haskell package](https://hackage.haskell.org/package/free) by Edward Kmett. //! //! # What is a Free Monad? //! A Free Monad is the left-adjoint to the Forget-Functor from the category of Monads into the category of Endofunctors. @@ -40,6 +40,10 @@ //! //! See the [blog post about this crate](https://www.grois.info/posts/2023-03/2023-03-11-adventures-with-free-monads-and-higher.xhtml) //! for a more detailed explanation. +//! +//! # A word of warning: +//! This crate should be considered a proof-of-concept. Its memory complexity is horrendous, and the performance of the Free Monad's [`Apply`][higher::Apply] +//! implementation can only be described as abysmal due to its reliance on deep copies. pub extern crate higher; @@ -57,6 +61,12 @@ pub extern crate higher; /// it is typically not necessary to have a fully fledged [`Monad`][higher::Monad]. In most use cases, it's enough to have /// [`Functor`][higher::Functor] + [`Bind`][higher::Bind] + [`Pure`][higher::Pure]. /// +/// The Free Monad type is implemented recursively. It is therefore akin to a linked tree, with all the respective performance implications. +/// +/// Furthermore, the implementation of [`Apply`][higher::Apply] creates a potentially high number of deep copies of the `self` parameter. +/// It should therefore be avoided, unless one really needs its +/// [tree-merging behaviour](https://www.grois.info/posts/2023-03/2023-03-11-adventures-with-free-monads-and-higher.xhtml#ugly_apply_drawing). +/// /// # Usage /// As stated above, the syntax to create a Free Monad is usually to call the macro with the desired Free Monad type as first, /// and the [`Functor`][higher::Functor] it should be based on as second parameter. @@ -330,7 +340,7 @@ macro_rules! free { #[cfg(test)] mod free_monad_tests{ - use higher::{Pure, Functor}; + use higher::{Pure, Functor, Bind}; use super::free; @@ -385,4 +395,28 @@ mod free_monad_tests{ } } + #[test] + fn test_bind_no_lifetime(){ + let f = FreeVec::lift_f(vec![1,2]); + let f = f.bind(|x| if x % 2 == 0 { FreeVec::lift_f(vec![x as f32,x as f32 + 1.0f32])} else { FreeVec::Pure(x as f32)}); + match f { + FreeVec::Free(f) => { + match &**f { + [FreeVec::Pure(a),FreeVec::Free(b)] => { + assert_eq!(*a, 1.0f32); + match &***b { + [FreeVec::Pure(a), FreeVec::Pure(b)] => { + assert_eq!(*a, 2.0f32); + assert_eq!(*b, 3.0f32); + }, + _ => unreachable!() + } + }, + _ => unreachable!() + } + }, + _ => unreachable!() + } + } + }
\ No newline at end of file |
