pub struct StateT<S, M, A> { /* private fields */ }
Expand description
A monad transformer that adds state capabilities to a base monad.
The StateT
type takes three type parameters:
S
: The state typeM
: The base monad type, which wraps a tuple of state and valueA
: The value type
§Examples
use rustica::transformers::StateT;
use rustica::prelude::*;
// Create a state transformer over Result that counts characters
let count_chars: StateT<usize, Result<(usize, usize), &str>, usize> = StateT::new(|state: usize| {
Ok((state + 1, state))
});
// Run with a specific initial state
let result = count_chars.run_state(5);
assert_eq!(result, Ok((6, 5)));
Implementations§
Source§impl<S, M, A> StateT<S, M, A>where
S: 'static,
M: 'static,
A: 'static,
impl<S, M, A> StateT<S, M, A>where
S: 'static,
M: 'static,
A: 'static,
Sourcepub fn new<F>(f: F) -> Self
pub fn new<F>(f: F) -> Self
Creates a new StateT
transformer.
§Parameters
f
- A function that takes a state and returns a monadic value containing a tuple of the new state and result
§Returns
A new StateT
instance
§Examples
use rustica::transformers::StateT;
use rustica::prelude::*;
// Create a StateT that modifies a numeric state and returns a derived value
let state_t: StateT<i32, Option<(i32, String)>, String> = StateT::new(|state: i32| {
if state <= 0 {
None
} else {
Some((state - 1, format!("Value: {}", state)))
}
});
assert_eq!(state_t.run_state(5), Some((4, "Value: 5".to_string())));
assert_eq!(state_t.run_state(0), None);
Sourcepub fn run_state(&self, state: S) -> M
pub fn run_state(&self, state: S) -> M
Runs the state transformer with a specific initial state.
§Parameters
state
- The initial state to run with
§Returns
The resulting monadic value containing the new state and result
§Examples
use rustica::transformers::StateT;
use rustica::prelude::*;
use std::collections::HashMap;
// Create a state that counts word frequencies
let count_word: StateT<HashMap<String, i32>, Option<(HashMap<String, i32>, i32)>, i32> =
StateT::new(|mut state: HashMap<String, i32>| {
let word = "hello".to_string();
let count = state.entry(word).or_insert(0);
*count += 1;
let result = *count;
Some((state, result))
});
// Run with an empty HashMap
let mut map = HashMap::new();
let result1 = count_word.run_state(map);
// Extract the state and result
let (new_state, count) = result1.unwrap();
assert_eq!(count, 1);
// Run again with the updated state
let result2 = count_word.run_state(new_state);
assert_eq!(result2.map(|(_, c)| c), Some(2));
Sourcepub fn get<P>(pure: P) -> StateT<S, M, S>
pub fn get<P>(pure: P) -> StateT<S, M, S>
Creates a StateT
that returns the current state without modifying it.
§Parameters
pure
- A function that lifts a value into the base monad
§Returns
A new StateT
that returns the current state
§Examples
use rustica::transformers::StateT;
use rustica::prelude::*;
// Create a StateT that gets the current state
let get_state = StateT::<i32, Option<(i32, i32)>, i32>::get(Some);
// Run with a specific state
let result = get_state.run_state(42);
assert_eq!(result, Some((42, 42)));
Sourcepub fn put<P>(new_state: S, pure: P) -> StateT<S, M, S>
pub fn put<P>(new_state: S, pure: P) -> StateT<S, M, S>
Creates a StateT
that replaces the current state and returns the old state.
§Parameters
new_state
- The new state to setpure
- Function to lift a value into the base monad
§Returns
A StateT
that updates the state
§Examples
use rustica::transformers::StateT;
use rustica::prelude::*;
// Create a StateT that sets a new state and returns the old one
let put_state = StateT::<i32, Result<(i32, i32), &str>, i32>::put(100, |t| Ok(t));
// Run with a specific state
let result = put_state.run_state(42);
assert_eq!(result, Ok((100, 42)));
Sourcepub fn modify<F, P>(f: F, pure: P) -> StateT<S, M, ()>
pub fn modify<F, P>(f: F, pure: P) -> StateT<S, M, ()>
Creates a StateT
that modifies the current state with a function.
§Parameters
f
- Function to modify the statepure
- Function to lift a value into the base monad
§Returns
A StateT
that modifies the state
§Examples
use rustica::transformers::StateT;
use rustica::prelude::*;
// Create a StateT that doubles the current state
let modify_state = StateT::<i32, Option<(i32, ())>, ()>::modify(|s| s * 2, |t| Some(t));
// Run with a specific state
let result = modify_state.run_state(21);
assert_eq!(result, Some((42, ())));
Sourcepub fn fmap_with<F, B, MapFn>(&self, f: F, map_fn: MapFn) -> StateT<S, M, B>
pub fn fmap_with<F, B, MapFn>(&self, f: F, map_fn: MapFn) -> StateT<S, M, B>
Maps a function over the values inside this StateT.
This is a specialized implementation that works with monads that have a map function.
§Parameters
f
- Function to apply to the valuesmap_fn
- Function that knows how to map over the base monad
§Returns
A new StateT with the function applied to its values
§Examples
use rustica::transformers::StateT;
use rustica::prelude::*;
// Create a state transformer over Option
let state_t: StateT<i32, Option<(i32, i32)>, i32> = StateT::new(|s: i32| {
Some((s + 1, s * 2))
});
// Map over the value using fmap_with
let doubled_state = state_t.fmap_with(
|n: i32| n + 10,
|m: Option<(i32, i32)>, f: Box<dyn Fn((i32, i32)) -> (i32, i32) + Send + Sync>| m.map(f)
);
assert_eq!(doubled_state.run_state(5), Some((6, 20)));
Sourcepub fn bind_with<F, B, BindFn, N>(
&self,
f: F,
bind_fn: BindFn,
) -> StateT<S, N, B>
pub fn bind_with<F, B, BindFn, N>( &self, f: F, bind_fn: BindFn, ) -> StateT<S, N, B>
Binds this StateT with a function that produces another StateT.
This is the monadic bind operation, which allows sequencing operations that depend on the result of previous operations.
§Parameters
f
- Function that takes a value and returns a new StateTbind_fn
- Function that knows how to perform bind on the base monad
§Returns
A new StateT representing the sequenced computation
§Examples
use rustica::transformers::StateT;
use rustica::prelude::*;
// Create a state that increments and returns the new value
let increment: StateT<i32, Option<(i32, i32)>, i32> =
StateT::new(|s: i32| Some((s + 1, s + 1)));
// Create a function that takes the output and produces another state transformer
let validate = |n: i32| {
StateT::new(move |s: i32| {
if n > 10 {
Some((s, n * 2))
} else {
Some((s, n))
}
})
};
// Compose using bind_with
let inc_and_validate: StateT<i32, Option<(i32, i32)>, i32> = increment.bind_with(
validate,
|m: Option<(i32, i32)>, f| m.and_then(|(s, a)| f((s, a)))
);
assert_eq!(inc_and_validate.run_state(5), Some((6, 6))); // <= 10, returns as-is
assert_eq!(inc_and_validate.run_state(10), Some((11, 22))); // > 10, doubles
Sourcepub fn combine_with<B, C, F, CombineFn>(
&self,
other: &StateT<S, M, B>,
f: F,
combine_fn: CombineFn,
) -> StateT<S, M, C>
pub fn combine_with<B, C, F, CombineFn>( &self, other: &StateT<S, M, B>, f: F, combine_fn: CombineFn, ) -> StateT<S, M, C>
Combines this StateT with another using a binary function.
This is useful for combining the results of two state operations that have the same state type.
§Parameters
other
- Another StateT to combine withf
- Function to combine the resultscombine_fn
- Function that knows how to combine values in the base monad
§Returns
A new StateT with the combined results
Sourcepub fn pure<P>(a: A, pure_fn: P) -> Self
pub fn pure<P>(a: A, pure_fn: P) -> Self
Creates a new StateT
transformer with a pure value.
This method lifts a pure value into the StateT
monad without changing
the current state. It’s the analog of State::pure
.
§Parameters
a
- The value to lift into the StateTpure_fn
- A function that lifts a tuple into the base monad
§Returns
A new StateT
containing the value and preserving the state
§Examples
use rustica::transformers::StateT;
// Create a StateT with a pure value
let state_t = StateT::<i32, Option<(i32, String)>, String>::pure("hello".to_string(), Some);
// Running with any state just returns the value and preserves the state
assert_eq!(state_t.run_state(42), Some((42, "hello".to_string())));
Sourcepub fn exec_state<F, B>(&self, s: S, extract_state_fn: F) -> Bwhere
F: FnOnce(M) -> B,
pub fn exec_state<F, B>(&self, s: S, extract_state_fn: F) -> Bwhere
F: FnOnce(M) -> B,
Runs the state computation and returns only the final state, discarding the value.
§Parameters
s
- The initial stateextract_state_fn
- Function that knows how to extract the state from the monadic result
§Returns
The final state after running the computation
§Examples
use rustica::transformers::StateT;
// Create a state that increments the state
let state_t = StateT::<i32, Option<(i32, String)>, String>::new(|s| {
Some((s + 1, format!("Value: {}", s)))
});
// Run and extract only the state
let result = state_t.exec_state(42, |opt| opt.map(|(s, _)| s));
assert_eq!(result, Some(43));
Sourcepub fn apply<B, C, ApplyFn>(
&self,
other: StateT<S, M, B>,
apply_fn: ApplyFn,
) -> StateT<S, M, C>
pub fn apply<B, C, ApplyFn>( &self, other: StateT<S, M, B>, apply_fn: ApplyFn, ) -> StateT<S, M, C>
Applies a function inside a StateT to a value inside another StateT. Applies a function inside a StateT to a value inside another StateT.
This is the applicative apply operation for StateT, allowing you to apply a function in a stateful context to a value in a stateful context.
§Parameters
other
- A StateT containing the value to apply the function toapply_fn
- A function that knows how to apply functions in the base monad
§Returns
A new StateT containing the result of applying the function to the value
§Examples
use rustica::transformers::StateT;
// Define a function that adds state to its argument
let fn_state: StateT<i32, Option<(i32, i32)>, i32> = StateT::new(|s: i32| {
Some((s + 1, 10))
});
// Define a state holding a value
let value_state: StateT<i32, Option<(i32, i32)>, i32> = StateT::new(|s: i32| {
Some((s * 2, 5))
});
// Apply the function to the value
let result: StateT<i32, Option<(i32, i32)>, i32> = fn_state.apply(value_state, |f_result, v_result| {
match (f_result, v_result) {
(Some((s1, f)), Some((s2, v))) => {
Some((s2, f + v)) // Using the second state, add the values
},
_ => None
}
});
// Run with state 10
// fn_state: returns (11, 10)
// value_state: returns (20, 5)
// apply: returns (20, 10 + 5) = (20, 15)
assert_eq!(result.run_state(10), Some((20, 15)));
Sourcepub fn join<JoinFn, OuterM>(&self, join_fn: JoinFn) -> StateT<S, OuterM, A>
pub fn join<JoinFn, OuterM>(&self, join_fn: JoinFn) -> StateT<S, OuterM, A>
Joins a nested StateT structure, flattening it to a single level.
This is useful when working with operations that return StateT instances inside StateT, allowing you to flatten the nested structure.
§Parameters
join_fn
- Function that knows how to join/flatten the base monad
§Returns
A flattened StateT instance
§Examples
use rustica::transformers::StateT;
// Create a nested StateT (StateT inside StateT)
let nested: StateT<i32, Option<(i32, StateT<i32, Option<(i32, i32)>, i32>)>, StateT<i32, Option<(i32, i32)>, i32>> =
StateT::new(|s: i32| {
let inner = StateT::new(move |inner_s: i32| {
Some((inner_s * 2, inner_s + s))
});
Some((s + 1, inner))
});
// Flatten the structure
let flattened = nested.join(|m| {
m.and_then(|(outer_s, inner_state_t)| {
inner_state_t.run_state(outer_s)
})
});
// Run the flattened computation
// With initial state 10:
// 1. outer: (11, inner_state_t)
// 2. inner_state_t with state 11: (22, 21)
assert_eq!(flattened.run_state(10), Some((22, 21)));
Source§impl<S, E, A> StateT<S, Result<(S, A), E>, A>
impl<S, E, A> StateT<S, Result<(S, A), E>, A>
Sourcepub fn try_run_state(&self, state: S) -> Result<(S, A), AppError<E>>
pub fn try_run_state(&self, state: S) -> Result<(S, A), AppError<E>>
Runs the state transformer and converts errors to AppError for standardized error handling.
This method executes the state transformer with the given initial state and converts any errors to the standardized AppError type, providing consistent error handling across the library.
§Parameters
state
- Initial state
§Returns
Result containing either the state-value pair or an AppError
§Examples
use rustica::transformers::StateT;
use rustica::utils::error_utils::AppError;
// Create a StateT that may fail with division
let safe_div: StateT<i32, Result<(i32, i32), String>, i32> = StateT::new(|s: i32| {
if s == 0 {
Err("Division by zero".to_string())
} else {
Ok((s, 100 / s))
}
});
// Convert regular errors to AppError
let result = safe_div.try_run_state(4);
assert!(result.is_ok());
assert_eq!(result.unwrap(), (4, 25)); // 100/4 = 25
// With error
let result = safe_div.try_run_state(0);
assert!(result.is_err());
assert_eq!(result.unwrap_err().message(), &"Division by zero");
Sourcepub fn try_run_state_with_context<C>(
&self,
state: S,
context: C,
) -> Result<(S, A), AppError<E, C>>where
C: Clone + 'static,
pub fn try_run_state_with_context<C>(
&self,
state: S,
context: C,
) -> Result<(S, A), AppError<E, C>>where
C: Clone + 'static,
Runs the state transformer with context information for better error reporting.
This method is similar to try_run_state
but allows for adding context to the error,
which can provide more information about what was happening when the error occurred.
§Parameters
state
- Initial statecontext
- Context information to include with errors
§Returns
Result containing either the state-value pair or an AppError with context
§Examples
use rustica::transformers::StateT;
use rustica::utils::error_utils::AppError;
// Create a StateT that may fail with division
let safe_div: StateT<i32, Result<(i32, i32), String>, i32> = StateT::new(|s: i32| {
if s == 0 {
Err("Division by zero".to_string())
} else {
Ok((s, 100 / s))
}
});
// Run with context
let result = safe_div.try_run_state_with_context(4, "processing user input");
assert!(result.is_ok());
assert_eq!(result.unwrap(), (4, 25)); // 100/4 = 25
// With error and context
let result = safe_div.try_run_state_with_context(0, "processing user input");
assert!(result.is_err());
let error = result.unwrap_err();
assert_eq!(error.message(), &"Division by zero");
assert_eq!(error.context(), Some(&"processing user input"));
Sourcepub fn map_error<F, E2>(&self, f: F) -> StateT<S, Result<(S, A), E2>, A>
pub fn map_error<F, E2>(&self, f: F) -> StateT<S, Result<(S, A), E2>, A>
Maps a function over the error contained in this StateT.
This method transforms the error type of the StateT, allowing for conversion between different error types while preserving the structure of the StateT.
§Parameters
f
- Function to apply to the error
§Returns
A new StateT with the mapped error
§Examples
use rustica::transformers::StateT;
// Create a StateT with a string error
let state_t: StateT<i32, Result<(i32, i32), String>, i32> = StateT::new(|s: i32| {
if s == 0 {
Err("Division by zero".to_string())
} else {
Ok((s, 100 / s))
}
});
// Map the error to a different type
let mapped = state_t.map_error(|e: String| e.len() as i32);
// Now the error is an i32 (the length of the original error string)
let result = mapped.run_state(0);
assert_eq!(result, Err(16)); // "Division by zero" has length 16
Sourcepub fn try_eval_state(&self, state: S) -> Result<A, AppError<E>>
pub fn try_eval_state(&self, state: S) -> Result<A, AppError<E>>
Runs the state transformer and returns only the value as a Result with AppError.
This method is similar to try_run_state
but discards the final state and
only returns the computed value.
§Parameters
state
- Initial state
§Returns
Result containing either the computed value or an AppError
§Examples
use rustica::transformers::StateT;
use rustica::utils::error_utils::AppError;
let safe_div: StateT<i32, Result<(i32, i32), String>, i32> = StateT::new(|s: i32| {
if s == 0 {
Err("Division by zero".to_string())
} else {
Ok((s, 100 / s))
}
});
let result = safe_div.try_eval_state(4);
assert_eq!(result, Ok(25)); // 100/4 = 25
let result = safe_div.try_eval_state(0);
assert!(result.is_err());
assert_eq!(result.unwrap_err().message(), &"Division by zero");
Sourcepub fn try_eval_state_with_context<C>(
&self,
state: S,
context: C,
) -> Result<A, AppError<E, C>>where
C: Clone + 'static,
pub fn try_eval_state_with_context<C>(
&self,
state: S,
context: C,
) -> Result<A, AppError<E, C>>where
C: Clone + 'static,
Runs the state transformer with context and returns only the value as a Result with AppError.
This method is similar to try_run_state_with_context
but discards the final state
and only returns the computed value.
§Parameters
state
- Initial statecontext
- Context information to include with errors
§Returns
Result containing either the computed value or an AppError with context
§Examples
use rustica::transformers::StateT;
use rustica::utils::error_utils::AppError;
let safe_div: StateT<i32, Result<(i32, i32), String>, i32> = StateT::new(|s: i32| {
if s == 0 {
Err("Division by zero".to_string())
} else {
Ok((s, 100 / s))
}
});
let result = safe_div.try_eval_state_with_context(4, "processing user input");
assert_eq!(result, Ok(25)); // 100/4 = 25
let result = safe_div.try_eval_state_with_context(0, "processing user input");
assert!(result.is_err());
let error = result.unwrap_err();
assert_eq!(error.message(), &"Division by zero");
assert_eq!(error.context(), Some(&"processing user input"));
Sourcepub fn try_exec_state(&self, state: S) -> Result<S, AppError<E>>
pub fn try_exec_state(&self, state: S) -> Result<S, AppError<E>>
Runs the state transformer and returns only the final state as a Result with AppError.
This method is similar to try_run_state
but discards the computed value and
only returns the final state.
§Parameters
state
- Initial state
§Returns
Result containing either the final state or an AppError
§Examples
use rustica::transformers::StateT;
use rustica::utils::error_utils::AppError;
let safe_div: StateT<i32, Result<(i32, i32), String>, i32> = StateT::new(|s: i32| {
if s == 0 {
Err("Division by zero".to_string())
} else {
Ok((s + 1, 100 / s))
}
});
let result = safe_div.try_exec_state(4);
assert_eq!(result, Ok(5)); // initial state 4 + 1 = 5
let result = safe_div.try_exec_state(0);
assert!(result.is_err());
assert_eq!(result.unwrap_err().message(), &"Division by zero");
Source§impl<S, A> StateT<S, Id<(S, A)>, A>
impl<S, A> StateT<S, Id<(S, A)>, A>
Sourcepub fn to_state(self) -> State<S, A>
pub fn to_state(self) -> State<S, A>
Converts this StateT<S, Id<(S, A)>, A>
into a State<S, A>
.
This method allows you to convert a state transformer with the identity monad as its base
back into a regular State
monad. This is useful when you want to drop the transformer
context and work with the simpler state monad.
§Examples
use rustica::transformers::StateT;
use rustica::datatypes::id::Id;
use rustica::datatypes::state::State;
// Create a StateT with Id as the monad
let state_t: StateT<i32, Id<(i32, i32)>, i32> = StateT::new(|s: i32| {
Id::new((s * 2, s + 1))
});
// Convert to State
let state: State<i32, i32> = state_t.to_state();
// The behavior should be identical
assert_eq!(state.run_state(21), (22, 42));
Sourcepub fn from_state(state: State<S, A>) -> Self
pub fn from_state(state: State<S, A>) -> Self
Converts a State<S, A>
into a StateT<S, Id<(S, A)>, A>
.
This method allows you to lift a regular state monad into the transformer context with the identity monad as the base. This is useful for composing stateful computations with other monad transformers.
§Examples
use rustica::datatypes::state::State;
use rustica::datatypes::id::Id;
use rustica::traits::identity::Identity;
use rustica::transformers::StateT;
// Create a State
let state = State::new(|s: i32| (s * 2, s + 1));
// Convert to StateT
let state_t: StateT<i32, Id<(i32, i32)>, i32> = StateT::from_state(state);
// The behavior should be identical
assert_eq!(state_t.run_state(21).value(), &(22, 42));
Trait Implementations§
Source§impl<S, A> From<StateT<S, Id<(A, S)>, A>> for State<S, A>
Allows conversion from a StateT<S, Id<(A, S)>, A>
to a State<S, A>
.
impl<S, A> From<StateT<S, Id<(A, S)>, A>> for State<S, A>
Allows conversion from a StateT<S, Id<(A, S)>, A>
to a State<S, A>
.
This implementation enables seamless conversion from the transformer type to the base type,
following the same pattern as Reader
and ReaderT
. Typically, this is only valid when the
base monad is Id
and the output is a tuple (A, S)
.
§Examples
use rustica::datatypes::state::State;
use rustica::transformers::state_t::StateT;
use rustica::datatypes::id::Id;
// Create a StateT that increments the state
let state_t: StateT<i32, Id<(i32, i32)>, i32> = StateT::new(|s| Id::new((s + 1, s + 1)));
// Convert to State
let state: State<i32, i32> = State::from(state_t);
assert_eq!(state.run_state(1), (2, 2));
Source§impl<S, M, A> MonadTransformer for StateT<S, M, A>
impl<S, M, A> MonadTransformer for StateT<S, M, A>
Auto Trait Implementations§
impl<S, M, A> Freeze for StateT<S, M, A>
impl<S, M, A> !RefUnwindSafe for StateT<S, M, A>
impl<S, M, A> Send for StateT<S, M, A>where
A: Send,
impl<S, M, A> Sync for StateT<S, M, A>where
A: Sync,
impl<S, M, A> Unpin for StateT<S, M, A>where
A: Unpin,
impl<S, M, A> !UnwindSafe for StateT<S, M, A>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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