rust-monadic
- A monad bloc macro based on Bind and Monad as supertraits of IntoIterator (iterables)
- A Reader monad bloc macro
- A ReaderT monad transformer bloc macro
- A Writer monad bloc macro
- A WriterT monad transformer bloc macro
- A State monad bloc macro
The macro mdo!
A macro to write Haskell style monadic code
for IntoIterator (iterables) as monads
Each step monad expression is flat_mapped with the rest into a lazy FlatMap expression which implements IntoIterator with lambdas as move closures capturing the environment and argument. The lambda body will be recursively parsed as monadic, and its type should also be an instance of IntoIterator.
Aside from the types that implement IntoIterator, all iterators also do it as documented.
The traits Bind and Monad are defined in module monad as supertraits of IntoIterator.
Here is a table where a monadic_expression is one of a type which must be instance of IntoIterator:
Note: let, within the macro, introduces only one binding.
Example1: monadic comprehensions à la Haskell (file: examples/comprehension.rs)
use ;
use Integer;
Execution:
Example2: variation with references to container and lambda argument position (file: examples/comprehension2.rs)
use ;
use Integer;
Execution:
Example: console io. If you want to return String variables, you may do it through cloning
// example console io
use ;
The Reader monad macro rdrdo!
A Reader monad adaptation macro example
//! examples/reader1
//!
//! You must specify in a type restriction the type of the environment of the Reader bloc
//!
//! `local` can be used as a function or as a method
use ;
use partial;
use HashMap;
type Env = ;
Execution:
)
The ReaderT monad transformer macro rdrt_mdo!
This monad transformer is strict and works only for monads that implement Monad + FromIterator + Clone
, e.g. Vec, LinkedList and VecDeque but not Option and Result which collect values in an container inside.
This macro requires more type annotations, as the inner monad and the lambda argument may be undetermined.
Instead of returning with pure return_expression
do it specifying the inner monad as
lift Vec::pure( return_expression)
Let bindings are not supported here. Instead you can use
v <- lift Vec::pure(expression)
Example:
// examples/reader_trans1.rs
use ;
use Integer;
use partial;
use HashMap;
type Env = ;
Execution:
Example using LinkedList instead of Vec:
// examples/reader_trans2
use ;
use Integer;
use partial;
use ;
type Env = ;
It yields the same result using LinkedList as using Vec.
The Writer monad macro wrdo!
A Writer monad adaptation macro example with String as logger, from examples/writer1.rs
//! examples/writer1.rs
//!
//! you may set the logger type
//! by beginning with a `tell...` function within the macro `wrdo`
//! or by declaring it as the result type
//! where String is the default if omitted
//! as in `let res : Writer< _, String > = wrdo!{...}`
//!
//! `censor(), listen() and listens()` can be used as functions or as methods of a Writer bloc
use ;
use concat_string_str;
use partial;
Exec:
) )
Example 2 with Vec as logger from examples/writer2.rs
//! examples/writer2.rs
//!
//! you may set the logger type
//! by beginning with a `tell...` function within the macro `wrdo`
//! or by declaring it as the result type
//! where String is the default if omitted
//! as in `let res : Writer< _, Vec<_> > = wrdo!{...}`
//!
//! `censor(), listen() and listens()` can be used as functions or as methods of a Writer bloc
use ;
use concat_vec_array;
use partial;
) )
The WriterT monad transformer macro wrt_mdo!
Only for Vec, LinkedList or VecDeque as inner monads.
Example:
//! examples/writer_trans1.rs
//!
//! you may set the logger type
//! by beginning with a `tell...` function within the macro `wrdo`
//! or by declaring it as the result type
//! where String is the default if omitted
//! as in `let res : Writer< _, String > = wrdo!{...}`
//!
//! `censor(), listen() and listens()` can be used as functions or as methods of a Writer bloc
use ;
use concat_string_str;
use partial;
use Integer;
Execution:
The State monad macro stdo!
A State monad adaptation macro example from examples/state1.rs
//! examples/state1.rs
//!
//! You may specify in a type restriction the type of the State bloc
//! or apply it directly to an initial_state without the type restriction
use ;
) )
Some tests:
; ; ; ;
Changes:
v. 0.4.8: added the WriterT transformer for (Vec, LinkedList, VecDeque) as nested monads
v. 0.4.7: added the ReaderT transformer for (Vec, LinkedList, VecDeque) as nested monads
v. 0.4.5 and 0.4.6: doc cleaning
v. 0.4.4: doc cleaning of old intoiter macro refs. Suppressed experimental MonadPlus, which is not ready.
v. 0.4.3: readme typos.
v. 0.4.2: added MonadPlus with quickcheck tests
v. 0.4.1: console_io example showing String return through cloning
v. 0.4.0:
- renamed writer function
censor_do
as censor - added writer function listen() and listens()
- renamed local_do() as local()
- removed intoiter module as it duplicates functionality without added applicability, use module monad's
mdo
macro instead
v. 0.3.14: added writer function censor_do
v. 0.3.13: added reader function local_do
v. 0.3.12: example reader1 simplification.
v. 0.3.11: suppressed the form "&v <- ..." from Writer and State monads.
v. 0.3.10: Added the Reader macro. It runs good over clonable environments e.g. HashMap. The State macro has been updated, using a non static lifetime for the boxed closure
v. 0.3.9: Added (<-) rhs pure
.