Skip to main content

Thunk

Struct Thunk 

Source
pub struct Thunk<'a, A>(/* private fields */);
Expand description

A deferred computation that produces a value of type A.

Thunk is NOT memoized - each call to Thunk::run re-executes the computation. This type exists to build computation chains without allocation overhead.

Unlike Trampoline, Thunk does NOT require 'static and CAN implement HKT traits like Functor, Semimonad, etc.

§Trade-offs vs Trampoline

AspectThunk<'a, A>Trampoline<A>
HKT compatible✅ Yes❌ No (requires 'static)
Stack-safe⚠️ Partial (tail_rec_m only)✅ Yes (unlimited)
Lifetime'a (can borrow)'static only
Use caseGlue code, compositionDeep recursion, pipelines

§Algebraic Properties

Thunk is a proper Monad:

  • pure(a).run() == a (left identity).
  • eval.bind(pure) == eval (right identity).
  • eval.bind(f).bind(g) == eval.bind(|a| f(a).bind(g)) (associativity).

§Type Parameters

  • A: The type of the value produced by the computation.

§Fields

  • 0: The closure that performs the computation.

§Examples

use fp_library::types::*;

let computation = Thunk::new(|| 5)
    .map(|x| x * 2)
    .map(|x| x + 1);

// No computation has happened yet!
// Only when we call run() does it execute:
let result = computation.run();
assert_eq!(result, 11);

Implementations§

Source§

impl<'a, A: 'a> Thunk<'a, A>

Source

pub fn new<F>(f: F) -> Self
where F: FnOnce() -> A + 'a,

Creates a new Thunk from a thunk.

§Type Signature

forall a. (Unit -> a) -> Thunk a

§Type Parameters
  • F: The type of the thunk.
§Parameters
  • f: The thunk to wrap.
§Returns

A new Thunk instance.

§Examples
use fp_library::types::*;

let eval = Thunk::new(|| 42);
assert_eq!(eval.run(), 42);
Source

pub fn pure(a: A) -> Self
where A: 'a,

Returns a pure value (already computed).

§Type Signature

forall a. a -> Thunk a

§Parameters
  • a: The value to wrap.
§Returns

A new Thunk instance containing the value.

§Examples
use fp_library::types::*;

let eval = Thunk::pure(42);
assert_eq!(eval.run(), 42);
Source

pub fn defer<F>(f: F) -> Self
where F: FnOnce() -> Thunk<'a, A> + 'a,

Defers a computation that returns an Thunk.

§Type Signature

forall a. (Unit -> Thunk a) -> Thunk a

§Type Parameters
  • F: The type of the thunk.
§Parameters
  • f: The thunk that returns an Thunk.
§Returns

A new Thunk instance.

§Examples
use fp_library::types::*;

let eval = Thunk::defer(|| Thunk::pure(42));
assert_eq!(eval.run(), 42);
Source

pub fn bind<B: 'a, F>(self, f: F) -> Thunk<'a, B>
where F: FnOnce(A) -> Thunk<'a, B> + 'a,

Monadic bind: chains computations.

Note: Each bind adds to the call stack. For deep recursion (>1000 levels), use Trampoline instead.

§Type Signature

forall b a. (a -> Thunk b, Thunk a) -> Thunk b

§Type Parameters
  • B: The type of the result of the new computation.
  • F: The type of the function to apply.
§Parameters
  • f: The function to apply to the result of the computation.
§Returns

A new Thunk instance representing the chained computation.

§Examples
use fp_library::types::*;

let eval = Thunk::pure(21).bind(|x| Thunk::pure(x * 2));
assert_eq!(eval.run(), 42);
Source

pub fn map<B: 'a, F>(self, f: F) -> Thunk<'a, B>
where F: FnOnce(A) -> B + 'a,

Functor map: transforms the result.

§Type Signature

forall b a. (a -> b, Thunk a) -> Thunk b

§Type Parameters
  • B: The type of the result of the transformation.
  • F: The type of the transformation function.
§Parameters
  • f: The function to apply to the result of the computation.
§Returns

A new Thunk instance with the transformed result.

§Examples
use fp_library::types::*;

let eval = Thunk::pure(21).map(|x| x * 2);
assert_eq!(eval.run(), 42);
Source

pub fn run(self) -> A

Forces evaluation and returns the result.

§Type Signature

forall a. Thunk a -> a

§Returns

The result of the computation.

§Examples
use fp_library::types::*;

let eval = Thunk::pure(42);
assert_eq!(eval.run(), 42);

Trait Implementations§

Source§

impl<'a, A: 'a> Defer<'a> for Thunk<'a, A>

Source§

fn defer<FnBrand: 'a + CloneableFn>( f: <FnBrand as CloneableFn>::Of<'a, (), Self>, ) -> Self
where Self: Sized,

Creates a value from a computation that produces the value. Read more
Source§

impl<'a, A, Config> From<Lazy<'a, A, Config>> for Thunk<'a, A>
where A: Clone + 'a, Config: LazyConfig,

Source§

fn from(lazy: Lazy<'a, A, Config>) -> Self

Converts to this type from the input type.
Source§

impl<'a, A> From<Thunk<'a, A>> for Lazy<'a, A, RcLazyConfig>

Source§

fn from(eval: Thunk<'a, A>) -> Self

Converts to this type from the input type.
Source§

impl<'a, A: 'a, E: 'a> From<Thunk<'a, A>> for TryThunk<'a, A, E>

Source§

fn from(eval: Thunk<'a, A>) -> Self

Converts to this type from the input type.
Source§

impl<'a, A: Monoid + 'a> Monoid for Thunk<'a, A>

Source§

fn empty() -> Self

Returns the identity Thunk.

§Type Signature

forall a. Monoid a => () -> Thunk a

§Returns

A Thunk producing the identity value of A.

§Examples
use fp_library::{classes::*, types::*};

let t: Thunk<String> = Monoid::empty();
assert_eq!(t.run(), "");
Source§

impl<'a, A: Semigroup + 'a> Semigroup for Thunk<'a, A>

Source§

fn append(a: Self, b: Self) -> Self

Combines two Thunks by combining their results.

§Type Signature

forall a. Semigroup a => (Thunk a, Thunk a) -> Thunk a

§Parameters
  • a: The first eval.
  • b: The second eval.
§Returns

A new Thunk containing the combined result.

§Examples
use fp_library::{brands::*, classes::*, functions::*};

let t1 = pure::<ThunkBrand, _>("Hello".to_string());
let t2 = pure::<ThunkBrand, _>(" World".to_string());
let t3 = Semigroup::append(t1, t2);
assert_eq!(t3.run(), "Hello World");

Auto Trait Implementations§

§

impl<'a, A> Freeze for Thunk<'a, A>

§

impl<'a, A> !RefUnwindSafe for Thunk<'a, A>

§

impl<'a, A> !Send for Thunk<'a, A>

§

impl<'a, A> !Sync for Thunk<'a, A>

§

impl<'a, A> Unpin for Thunk<'a, A>

§

impl<'a, A> !UnwindSafe for Thunk<'a, A>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.