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}