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 中使用

Apache-2.0

135KB
2K SLoC

rust2fun (发音:rʌstafʌn)

Crates.io docs.rs build

用于 Rust 的函数式编程库。

构建

默认情况下,库使用启用 std 功能构建。要禁用它,请使用 --no-default-features 标志。

用法

将此添加到您的 Cargo.toml

[dependencies]
rust2fun = "0.2.1"

并导入预定义

use rust2fun::prelude::*;

支持的功能

组合子

类型类

数据类型

示例

  1. 函数 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());
  1. 累积所有错误的有效性。

假设我们有一些需要应用于创建新信用卡的验证规则

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(如示例中所示)或其他半群(例如 Stringu32等)来创建一个新的信用卡。

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)
}
  1. 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
  • 将宏导入移动到预定义中
  • 添加了 noopXtupleX 函数集
  • 添加了类型类:Semigroup、Monoid、Bifunctor + Higher2(感谢 lrind
  • 添加了数据类型:NEVec、Validated
  • 添加了 bind! 符号
  • 多个修复和改进

0.2.1 (2023-09-21)

  • 修复了 Semigroupal 和 Apply 的行为(感谢 GoldsteinE 提供的报告)
  • 添加了类型类:Pure、AndThen
  • 重构了 mapXapX 函数

依赖关系

~0.4–0.8MB
~20K SLoC