#currying #compose #function #composition #fp

nightly currycompose

A crate providing a trait for performing currying (and non-currying) function-composition in rust

1 unstable release

0.1.0 Mar 20, 2023

#4 in #currying

MIT license

10KB
91 lines

currycompose

A crate providing a trait for performing currying (and non-currying) function-composition in rust.

A can be composed with B if A implements FnOnce and takes one or more argument, while B implements FnOnce and returns something of the same type as the first argument of A.

  • For instance (A, B) -> Y can be composed with (C) -> A, yiedling (B, C) -> Y (currying).

  • Composing (A, B) -> Y with (C) -> A then with (D) -> B yields (C, D) -> Y (currying twice).

  • While of course (A) -> Y composed with (B) -> A, yields (B) -> Y as expected (non-currying composition).

Currying functions which implement FnMut or Fn will yield something also implementing FnMut/Fn if both operands do.


lib.rs:

https://en.wikipedia.org/wiki/Function_composition

A crate providing a trait for performing currying (and non-currying) function-composition in rust.

Non-currying composition: h(x) = g ∘ f = g(f(x))

Currying composition: h(..., x) = g ∘ f = g(f(x), ...)

When currying, arguments of the function being curried with (f) is moved to the end of the argument-list

Both operands must implement FnOnce. If both implement FnMut or Fn, the resulting composition will also implement these traits.

g must also have one or more argument, where the first argument type equals the return type of f.

#![feature(generic_const_exprs)]

use currycompose::*;

// g ∘ f
// where
// g :: f32 -> f32
// f :: u8 -> f32
// g ∘ f :: u8 -> f32
let g = |x: f32| x*x;
let f = |x: u8| x as f32;

let gf = g.compose(f);

let x = 1;

assert_eq!(gf(x), g(f(x)));

// g ∘ f
// where
// g :: f32 -> f32 -> f32
// f :: u8 -> f32
// g ∘ f :: f32 -> u8 -> f32
let g = |x: f32, y: f32| x + y;
let f = gf;

let gf = g.compose(f);

let x = 1;
let y = 1.0;

// note here the argument x has been shifted to the end of the args in gf
assert_eq!(gf(y, x), g(f(x), y));

// g ∘ f ∘ f
// where
// g :: f32 -> f32 -> f32
// f :: u8 -> f32
// g ∘ f ∘ f :: u8 -> u8 -> f32
let gff = gf.compose(f);

let x = 1;
let y = 1;

assert_eq!(gff(x, y), g(f(x), f(y)));

Dependencies

~1.5MB
~37K SLoC