6 个版本
使用旧的 Rust 2015
0.0.7 | 2016 年 10 月 20 日 |
---|---|
0.0.6 | 2016 年 10 月 20 日 |
#1147 in Rust 模式
34 每月下载量
47KB
1K SLoC
Frust
在 Rust 中的实用函数式编程工具集。仍然主要是一个 WIP。
总体思路是通过在 Rust 中提供 FP 工具来简化事物,以便进行类似这样的操作
use frust::monoid::*;
let v = vec![Some(1), Some(3)];
assert_eq!(combine_all(&v), Some(4));
// Slightly more magical
let t1 = (1, 2.5f32, String::from("hi"), Some(3));
let t2 = (1, 2.5f32, String::from(" world"), None);
let t3 = (1, 2.5f32, String::from(", goodbye"), Some(10));
let tuples = vec![t1, t2, t3];
let expected = (3, 7.5f32, String::from("hi world, goodbye"), Some(13));
assert_eq!(combine_all(&tuples), expected);
目录
示例
幺半群
可以组合的事物。
use frust::semigroup::*;
assert_eq!(Some(1).combine(&Some(2)), Some(3));
assert_eq!(All(3).combine(&All(5)), All(1)); // bit-wise &&
assert_eq!(All(true).combine(&All(false)), All(false));
半群
可以组合 并且 具有空/标识值的事物。
use frust::monoid::*;
let t1 = (1, 2.5f32, String::from("hi"), Some(3));
let t2 = (1, 2.5f32, String::from(" world"), None);
let t3 = (1, 2.5f32, String::from(", goodbye"), Some(10));
let tuples = vec![t1, t2, t3];
let expected = (3, 7.5f32, String::from("hi world, goodbye"), Some(13));
assert_eq!(combine_all(&tuples), expected)
let product_nums = vec![Product(2), Product(3), Product(4)];
assert_eq!(combine_all(&product_nums), Product(24))
HList
静态类型异构列表。从这些列表中弹出多少都可以;所有内容都保持类型化。
#[macro_use] extern crate frust;
use frust::hlist::*;
let h = hlist![true, "hello", Some(41)];
let (h1, tail1) = h.pop();
assert_eq!(h1, true);
assert_eq!(tail1, hlist!["hello", Some(41)]);
验证
Validated
是执行一系列可能会出错的操作(例如,返回 Result<T, E>
的函数)的方式,在出现一个或多个错误的情况下,将所有错误一次性返回给你。如果一切顺利,你将获得一个包含所有结果的 HList
。
映射(以及使用纯 Result
)是不同的,因为它会在遇到第一个错误时停止,这在非常常见的情况下可能会很烦人(如 Cats 项目 所概述的)。
以下是如何使用它的示例。
#[derive(PartialEq, Eq, Debug)]
struct Person {
age: i32,
name: String,
}
fn get_name() -> Result<String, Error> { /* elided */ }
fn get_age() -> Result<i32, Error> { /* elided */ }
// Build up a `Validated`
let validation = get_name().into_validated() + get_age();
// When needed, turn the `Validated` back into a Result and map as usual
let try_person = validation.into_result()
.map(|hlist| {
let (name, (age, _)) = hlist.into_tuple2();
Person {
name: name,
age: age,
}
});
assert_eq!(person,
Result::Ok(Person {
name: "James".to_owned(),
age: 32,
}));
/// This next pair of functions always return Recover::Err
fn get_name_faulty() -> Result<String, String> {
Result::Err("crap name".to_owned())
}
fn get_age_faulty() -> Result<i32, String> {
Result::Err("crap age".to_owned())
}
let validation2 = get_name_faulty().into_validated() + get_age_faulty();
let try_person2 = validation2.into_result()
.map(|_| unimplemented!());
// Notice that we have an accumulated list of errors!
assert_eq!(try_person2,
Result::Err(vec!["crap name".to_owned(), "crap age".to_owned()]));
待办事项
最好从实现那些对惯用 Rust 语法使用有用的东西开始(高效且安全)。以下可能很有用
- 验证(见 cats)
这些功能根本未实现,而且由于Rust不支持高阶类型,我也没有确切知道它们是否可能实现。此外,Rustaceans习惯于在集合上调用iter()
来获取懒视图,操作它们的列表,然后在最后进行collect()
来保持效率。在这些结构中的应用可能受到限制。
函子
单子
应用
应用函子
Show
、Monoid
、HList
和Semigroup
至少部分(大多数?)已实现。
基准测试会很棒,但它们是一个不稳定的特性,所以也许在不同的分支中。
贡献
是的,请!
以下内容被认为是重要的,符合Rust和函数式编程的精神。
- 安全性(类型和内存)
- 效率
- 正确性
灵感
Scalaz、Cats、Haskell,常见的候选者 ;)