1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
#![doc(html_playground_url = "https://play.rust-lang.org/")] //! Frunk: generic functional programming toolbelt for Rust //! //! Aims to be a collection of functional programming abstractions implemented in Rust //! in effective, useful, and idiomatic ways. Examples of things that are included in rust are: //! //! 1. HLists (heterogeneously-typed lists) //! 2. Validated (accumulator for Result) //! 3. Semigroup //! 4. Monoid //! //! Here is a small taste of what Frunk has to offer: //! //! ``` //! # #[macro_use] extern crate frunk; //! # #[macro_use] extern crate frunk_core; //! # use frunk_core::hlist::*; fn main() { //! use frunk_core::hlist::*; //! use frunk_core::generic::*; //! use frunk_core::labelled::*; //! use frunk::monoid::*; //! use frunk::semigroup::*; //! use frunk::validated::*; //! //! // Combining Monoids //! let v = vec![Some(1), Some(3)]; //! assert_eq!(combine_all(&v), Some(4)); //! //! // HLists //! let h = hlist![1, "hi"]; //! assert_eq!(h.length(), 2); //! let hlist_pat!(a, b) = h; //! assert_eq!(a, 1); //! assert_eq!(b, "hi"); //! //! let h1 = hlist![Some(1), 3.3, 53i64, "hello".to_owned()]; //! let h2 = hlist![Some(2), 1.2, 1i64, " world".to_owned()]; //! let h3 = hlist![Some(3), 4.5, 54, "hello world".to_owned()]; //! assert_eq!(h1.combine(&h2), h3); //! //! // Generic and LabelledGeneric-based programming //! // Allows Structs to play well easily with HLists //! //! #[derive(Generic, LabelledGeneric)] //! struct ApiUser<'a> { //! FirstName: &'a str, //! LastName: &'a str, //! Age: usize, //! } //! //! #[derive(Generic, LabelledGeneric)] //! struct NewUser<'a> { //! first_name: &'a str, //! last_name: &'a str, //! age: usize, //! } //! //! #[derive(LabelledGeneric)] //! struct SavedUser<'a> { //! first_name: &'a str, //! last_name: &'a str, //! age: usize, //! } //! //! // Instantiate a struct from an HList. Note that you can go the other way too. //! let a_user: ApiUser = from_generic(hlist!["Joe", "Blow", 30]); //! //! // Convert using Generic //! let n_user = <NewUser as Generic>::convert_from(a_user); // done //! //! // Convert using LabelledGeneric //! // //! // This will fail if the fields of the types converted to and from do not //! // have the same names or do not line up properly :) //! // //! // Also note that we're using a helper method to avoid having to use universal //! // function call syntax //! let s_user: SavedUser = labelled_convert_from(n_user); //! //! assert_eq!(s_user.first_name, "Joe"); //! assert_eq!(s_user.last_name, "Blow"); //! assert_eq!(s_user.age, 30); //! //! // Uh-oh ! last_name and first_name have been flipped! //! #[derive(LabelledGeneric)] //! struct DeletedUser<'a> { //! last_name: &'a str, //! first_name: &'a str, //! age: usize, //! } //! // let d_user = <DeletedUser as LabelledGeneric>::convert_from(s_user); <-- this would fail at compile time :) //! //! // This will, however, work, because we make use of the Sculptor type-class //! // to type-safely reshape the representations to align/match each other. //! let d_user: DeletedUser = sculpted_convert_from(s_user); //! assert_eq!(d_user.first_name, "Joe"); //! # } //! ``` //! //! Links: //! 1. [Source on Github](https://github.com/lloydmeta/frunk) //! 2. [Crates.io page](https://crates.io/crates/frunk) #[macro_use] extern crate frunk_core; #[macro_use] extern crate frunk_derives; pub mod semigroup; pub mod monoid; pub mod validated; pub use frunk_core::hlist::*; pub use frunk_core::labelled::*; // this needs to be globally imported in order for custom derives to work w/o fuss pub use frunk_core::generic::*; pub use frunk_derives::*;