3 个不稳定版本
0.2.1 | 2023 年 9 月 21 日 |
---|---|
0.2.0 | 2023 年 9 月 10 日 |
0.1.0 | 2023 年 1 月 22 日 |
#443 in Rust 模式
38 个月下载量
在 rust2fun_laws 中使用
135KB
2K SLoC
rust2fun (发音:rʌstafʌn)
用于 Rust 的函数式编程库。
构建
默认情况下,库使用启用 std
功能构建。要禁用它,请使用 --no-default-features
标志。
用法
将此添加到您的 Cargo.toml
[dependencies]
rust2fun = "0.2.1"
并导入预定义
use rust2fun::prelude::*;
支持的功能
组合子
- 函数组合(使用 compose 宏)
- 管道(使用 pipe 宏)
- 柯里化
- 参数反转(使用 flip 宏)
- 常量函数
- id(I 拉姆达算子)
- apply(A 拉姆达算子)
- apply_to(T 拉姆达算子)
- substitution(S 拉姆达算子)
- 收敛
- on(Psi 拉姆达算子)
- if_else
- fix(Y 拉姆达算子)
- 无操作
- 元组构造函数
类型类
数据类型
示例
- 函数
print_user_credit_card
接受任何效果(Option、Result、Vec等)包装的用户,并打印相应的信用卡。
fn get_credit_card(user: User) -> CreditCard {
// Get credit card for user
}
fn print_credit_card(card: CreditCard) {
// Print credit card details
}
fn print_credit_card_of<F>(user: F)
where
F: Functor<CreditCard, Param=User>,
F::Target<CreditCard>: Functor<(), Param=CreditCard>,
{
user.map(get_credit_card).map(print_credit_card);
}
...使用
fn user(id: u32) -> Option<User> {
// Get user from database
}
fn all_users() -> Vec<User> {
// Get all users from database
}
print_credit_card_of(user(1));
print_credit_card_of(all_users());
- 累积所有错误的有效性。
假设我们有一些需要应用于创建新信用卡的验证规则
fn validate_number(number: CreditCardNumber) -> Result<CreditCardNumber, Error> {
// Validating credit card number
}
fn validate_expiration(date: Date) -> Result<Date, Error> {
// Validating expiration date
}
fn validate_cvv(cvv: Code) -> Result<Code, Error> {
// Validating CVV code
}
...我们可以通过应用所有验证规则并收集所有错误到一个向量 Vec
,非空向量 NEVec
(如示例中所示)或其他半群(例如 String
、u32
等)来创建一个新的信用卡。
fn validate_credit_card(
number: CreditCardNumber,
expiration: Date,
cvv: Code,
) -> ValidatedNev<CreditCard, Error> {
ValidatedNev::pure(CreditCard::new)
.ap3(validate_number(number).into(),
validate_expiration(expiration).into(),
validate_cvv(cvv).into())
}
...或者,可以使用 map3
方法完成
fn validate_credit_card(
number: CreditCardNumber,
expiration: Date,
cvv: Code,
) -> ValidatedNev<CreditCard, Error> {
let number: ValidatedNev<_, _> = validate_number(number).into();
let expiration = validate_expiration(expiration).into();
let cvv = validate_cvv(cvv).into();
MapN::map3(number, expiration, cvv, CreditCard::new)
}
bind!
符号用于单子(类似于Haskell中的do
符号或Scala中的for
理解)
假设我们定义了以下函数
fn get_opening_prices() -> Vec<(AssetId, i32)> {
// Get opening prices from an external service
}
fn get_closing_prices() -> Vec<(AssetId, i32)> {
// Get closing prices from an external service
}
fn get_asset_name(id: AssetId) -> Option<String> {
// Recover asset name for the given id
}
...我们可以使用 bind!
符号来计算每个资产的日利润
let profits: Vec<(String, i32)> = bind! {
for (id_open, opening_price) in get_opening_prices();
for (id_close, closing_price) in get_closing_prices();
let diff = closing_price - opening_price;
for name in get_asset_name(id_open).into_iter().collect::<Vec<_>>(),
if id_open == id_close && diff > 0;
(name, diff)
};
发布说明
0.1.0 (2023-01-22)
- 首次发布:组合子、Semigroupal、Invariant、Functor、Apply、Applicative、FlatMap、Monad
0.2.0 (2023-09-10)
- 项目获得了其标志(感谢 olasinitsyna)
- 将宏导入移动到预定义中
- 添加了
noopX
和tupleX
函数集 - 添加了类型类:Semigroup、Monoid、Bifunctor + Higher2(感谢 lrind)
- 添加了数据类型:NEVec、Validated
- 添加了
bind!
符号 - 多个修复和改进
0.2.1 (2023-09-21)
- 修复了 Semigroupal 和 Apply 的行为(感谢 GoldsteinE 提供的报告)
- 添加了类型类:Pure、AndThen
- 重构了
mapX
和apX
函数
依赖关系
~0.4–0.8MB
~20K SLoC