Frunk
frunk frəNGk
- Functional programming toolbelt in Rust.
- Might seem funky at first, but you'll like it.
- Comes from: funktional (German) + Rust → Frunk
The general idea is to make things easier by providing FP tools in Rust to allow for stuff like this:
use *;
let v = vec!;
assert_eq!;
// Slightly more magical
let t1 = ;
let t2 = ;
let t3 = ;
let tuples = vec!;
let expected = ;
assert_eq!;
Table of Contents
Examples
Semigroup
Things that can be combined.
use *;
assert_eq!;
assert_eq!; // bit-wise &&
assert_eq!;
Monoid
Things that can be combined and have an empty/id value.
use *;
let t1 = ;
let t2 = ;
let t3 = ;
let tuples = vec!;
let expected = ;
assert_eq!
let product_nums = vec!;
assert_eq!
HList
Statically typed heterogeneous lists. Pop as much as you want from one of these; everything remains typed.
extern crate frunk;
use *;
let h = hlist!;
let = h.pop;
assert_eq!;
assert_eq!;
// HLists also have a .into_tuple2() method that convert HLists with 2 or more
// items into nested Tuple2s for a nicer type-signature and pattern-matching experience
let hl = hlist!;
let = hl.into_tuple2;
Validated
Validated
is a way of running a bunch of operations that can go wrong (for example,
functions returning Result<T, E>
) and, in the case of one or more things going wrong,
having all the errors returned to you all at once. In the case that everything went well, you get
an HList
of all your results.
Mapping (and otherwise working with plain) Result
s is different because it will
stop at the first error, which can be annoying in the very common case (outlined
best by the Cats project).
Here is an example of how it can be used.
// Build up a `Validated`
let validation = get_name.into_validated + get_age + get_street;
// When needed, turn the `Validated` back into a Result and map as usual
let try_person = validation.into_result
.map;
assert_eq!;
}
/// This next pair of functions always return Recover::Err
let validation2 = get_name_faulty.into_validated + get_age_faulty;
let try_person2 = validation2.into_result
.map;
// Notice that we have an accumulated list of errors!
assert_eq!;
Todo
Stabilise interface, general cleanup
Before a 1.0 release, would be best to revisit the design of the interfaces and do some general code (and test cleanup).
Benchmarks
Benchmarks would be nice but they're an unstable feature, so perhaps in a different branch ?
Not yet implemented
Given that Rust has no support for Higher Kinded Types, I'm not sure if these
are even possible to implement. In addition, Rustaceans are used to calling iter()
on collections to get a lazy view, manipulating their elements with map
or and_then
, and then doing a collect()
at the end to keep things
efficient. The usefulness of these following structures maybe limited in that context.
Functor
Monad
Apply
Applicative
Contributing
Yes please !
The following are considered important, in keeping with the spirit of Rust and functional programming:
- Safety (type and memory)
- Efficiency
- Correctness
Inspirations
Scalaz, Cats, Haskell, the usual suspects ;)