currying/curry.rs
1use core::marker::Tuple;
2
3use crate::Curried;
4
5/// A trait for things which may be curried.
6///
7/// C is the leftmost argument being applied in the curry.
8///
9/// X is the rest of the arguments left over after currying.
10///
11/// This trait is automatically implemented for anything implementing [FnOnce](core::ops::FnOnce) which takes one or more argument.
12///
13/// # Examples
14///
15/// ```rust
16/// use currying::*;
17///
18/// let f = |x, y, z| x + y + z;
19/// let (x, y, z) = (1, 2, 3);
20///
21/// let fx = f.curry(x);
22///
23/// assert_eq!(fx(y, z), f(x, y, z));
24///
25/// let fxy = fx.curry(y);
26///
27/// assert_eq!(fxy(z), f(x, y, z));
28///
29/// let fxyz = fxy.curry(z);
30///
31/// assert_eq!(fxyz(), f(x, y, z));
32/// ```
33pub trait Curriable<C, X: Tuple> = Curry<C, Output: FnOnce<X>>;
34
35/// A trait providing the method for currying from the left.
36///
37/// Only types that implement [FnOnce](core::ops::FnOnce) and can take a leftmost argument of type `C` can be called once curried.
38///
39/// # Examples
40///
41/// ```rust
42/// use currying::*;
43///
44/// let f = |x, y, z| x + y + z;
45/// let (x, y, z) = (1, 2, 3);
46///
47/// let fx = f.curry(x);
48///
49/// assert_eq!(fx(y, z), f(x, y, z));
50///
51/// let fxy = fx.curry(y);
52///
53/// assert_eq!(fxy(z), f(x, y, z));
54///
55/// let fxyz = fxy.curry(z);
56///
57/// assert_eq!(fxyz(), f(x, y, z));
58/// ```
59pub const trait Curry<C>: Sized
60{
61 type Output;
62
63 fn curry_once(self, arg: C) -> Self::Output;
64 fn curry_mut(&mut self, arg: C) -> <&mut Self as Curry<C>>::Output
65 {
66 self.curry_once(arg)
67 }
68 fn curry(&self, arg: C) -> <&Self as Curry<C>>::Output
69 {
70 self.curry_once(arg)
71 }
72}
73
74impl<C, F> const Curry<C> for F
75{
76 type Output = Curried<(C,), (), F>;
77
78 fn curry_once(self, arg: C) -> Self::Output
79 {
80 Curried::curry(self, arg)
81 }
82}