naan/fun/
compose.rs

1use core::marker::PhantomData;
2
3use super::{F1Once, F1};
4
5/// Struct capturing [`Sized`] function composition.
6///
7/// Implements [`F1`]/[`F1Once`] when `F` and `G`
8/// implement [`F1`]/[`F1Once`].
9///
10/// `X` is the "erased" type returned by `F` and passed
11/// to `G`, stored as [`PhantomData`] to make trait implementation
12/// simpler.
13///
14/// For examples, see [`F1Once::chain`].
15pub struct Compose<F, G, X> {
16  f: F,
17  g: G,
18  hidden_type: PhantomData<X>,
19}
20
21impl<F, G, X> Compose<F, G, X> {
22  /// See [`Compose`]
23  pub fn compose<A, B>(f: F, g: G) -> Self
24    where F: F1Once<A, Ret = X>,
25          G: F1Once<X, Ret = B>
26  {
27    Self { f,
28           g,
29           hidden_type: PhantomData }
30  }
31
32  /// See [`F1Once::chain`]
33  pub fn chain<A, B, X2, G2>(self, g2: G2) -> Compose<Compose<F, G, X>, G2, X2>
34    where F: F1Once<A, Ret = X>,
35          G: F1Once<X, Ret = X2>,
36          G2: F1Once<X2, Ret = B>
37  {
38    Compose { f: self,
39              g: g2,
40              hidden_type: PhantomData }
41  }
42}
43
44impl<F, G, A, X, C> F1Once<A> for Compose<F, G, X>
45  where F: F1Once<A, Ret = X>,
46        G: F1Once<X, Ret = C>
47{
48  type Ret = C;
49  fn call1(self, a: A) -> C {
50    self.g.call1(self.f.call1(a))
51  }
52}
53
54impl<F, G, A, X, C> F1<A> for Compose<F, G, X>
55  where F: F1<A, Ret = X>,
56        G: F1<X, Ret = C>
57{
58  fn call(&self, a: A) -> C {
59    self.g.call(self.f.call(a))
60  }
61}