1use crate::{
5 classes::{
6 Category, ClonableFn, Function, Monoid, Semigroup, Semigroupoid,
7 clonable_fn::ApplyClonableFn, function::ApplyFunction,
8 },
9 functions::{compose, identity},
10 hkt::{Apply1L2T, Kind1L2T},
11};
12use std::rc::Rc;
13
14#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub struct RcFnBrand;
23
24impl Kind1L2T for RcFnBrand {
25 type Output<'a, A, B> = Rc<dyn 'a + Fn(A) -> B>;
26}
27
28impl Function for RcFnBrand {
29 type Output<'a, A: 'a, B: 'a> = Apply1L2T<'a, Self, A, B>;
30
31 fn new<'a, A: 'a, B: 'a>(f: impl 'a + Fn(A) -> B) -> ApplyFunction<'a, Self, A, B> {
32 Rc::new(f)
33 }
34}
35
36impl ClonableFn for RcFnBrand {
37 type Output<'a, A: 'a, B: 'a> = Apply1L2T<'a, Self, A, B>;
38
39 fn new<'a, A: 'a, B: 'a>(f: impl 'a + Fn(A) -> B) -> ApplyClonableFn<'a, Self, A, B> {
40 Rc::new(f)
41 }
42}
43
44impl Semigroupoid for RcFnBrand {
45 fn compose<'a, ClonableFnBrand: 'a + ClonableFn, B, C, D>(
46 f: Apply1L2T<'a, Self, C, D>
47 ) -> ApplyClonableFn<'a, ClonableFnBrand, Apply1L2T<'a, Self, B, C>, Apply1L2T<'a, Self, B, D>>
48 {
49 <ClonableFnBrand as ClonableFn>::new::<'a, _, _>(move |g: Apply1L2T<'a, Self, B, C>| {
50 <Self as ClonableFn>::new::<'a, _, _>({
51 let f = f.clone();
52 move |a| compose::<'a, Self, _, _, _>(f.clone())(g.clone())(a)
53 })
54 })
55 }
56}
57
58impl Category for RcFnBrand {
59 fn identity<'a, A: 'a>() -> Apply1L2T<'a, Self, A, A> {
60 <Self as ClonableFn>::new::<'a, _, _>(identity)
61 }
62}
63
64impl<'b, A: 'b + Clone, B: Semigroup<'b> + 'b> Semigroup<'b> for Rc<dyn 'b + Fn(A) -> B> {
65 fn append<'a, ClonableFnBrand: 'a + 'b + ClonableFn>(
66 a: Self
67 ) -> ApplyClonableFn<'a, ClonableFnBrand, Self, Self>
68 where
69 Self: Sized,
70 'b: 'a,
71 {
72 <ClonableFnBrand as ClonableFn>::new(move |b: Self| {
73 <RcFnBrand as ClonableFn>::new({
74 let a = a.clone();
75 move |c: A| B::append::<ClonableFnBrand>(a(c.clone()))(b(c))
76 })
77 })
78 }
79}
80
81impl<'b, A: 'b + Clone, B: Monoid<'b> + 'b> Monoid<'b> for Rc<dyn 'b + Fn(A) -> B> {
82 fn empty() -> Self {
83 <RcFnBrand as ClonableFn>::new(move |_| B::empty())
84 }
85}