1use crate::{
4 classes::{
5 ClonableFn, Defer, Monoid, Once, Semigroup, clonable_fn::ApplyClonableFn, once::ApplyOnce,
6 },
7 hkt::Kind0L1T,
8};
9use core::fmt;
10use std::{
11 fmt::{Debug, Formatter},
12 hash::{Hash, Hasher},
13};
14
15pub struct Lazy<'a, OnceBrand: Once, ClonableFnBrand: ClonableFn, A: 'a>(
17 pub ApplyOnce<OnceBrand, A>,
18 pub ApplyClonableFn<'a, ClonableFnBrand, (), A>,
19);
20
21impl<'a, OnceBrand: Once, ClonableFnBrand: ClonableFn, A> Lazy<'a, OnceBrand, ClonableFnBrand, A> {
22 pub fn new(a: ApplyClonableFn<'a, ClonableFnBrand, (), A>) -> Self {
23 Self(OnceBrand::new(), a)
24 }
25
26 pub fn force(a: Self) -> A
27 where
28 A: Clone,
29 {
30 <OnceBrand as Once>::get_or_init(&a.0, move || (a.1)(())).clone()
31 }
32}
33
34impl<'a, OnceBrand: Once, ClonableFnBrand: ClonableFn, A: 'a + Clone> Clone
35 for Lazy<'a, OnceBrand, ClonableFnBrand, A>
36where
37 ApplyOnce<OnceBrand, A>: Clone,
38{
39 fn clone(&self) -> Self {
40 Self(self.0.clone(), self.1.clone())
41 }
42}
43
44impl<'a, OnceBrand: Once, ClonableFnBrand: ClonableFn, A: Debug> Debug
45 for Lazy<'a, OnceBrand, ClonableFnBrand, A>
46where
47 ApplyOnce<OnceBrand, A>: Debug,
48 ApplyClonableFn<'a, ClonableFnBrand, (), A>: Debug,
49{
50 fn fmt(
51 &self,
52 fmt: &mut Formatter<'_>,
53 ) -> fmt::Result {
54 fmt.debug_tuple("Lazy").field(&self.0).field(&self.1).finish()
55 }
56}
57
58impl<'a, OnceBrand: Once, ClonableFnBrand: ClonableFn, A: Eq> Eq
59 for Lazy<'a, OnceBrand, ClonableFnBrand, A>
60where
61 ApplyOnce<OnceBrand, A>: Eq,
62 ApplyClonableFn<'a, ClonableFnBrand, (), A>: Eq,
63{
64}
65
66impl<'a, OnceBrand: Once, ClonableFnBrand: ClonableFn, A: Hash> Hash
67 for Lazy<'a, OnceBrand, ClonableFnBrand, A>
68where
69 ApplyOnce<OnceBrand, A>: Hash,
70 ApplyClonableFn<'a, ClonableFnBrand, (), A>: Hash,
71{
72 fn hash<H: Hasher>(
73 &self,
74 state: &mut H,
75 ) {
76 self.0.hash(state);
77 self.1.hash(state);
78 }
79}
80
81impl<'a, OnceBrand: Once, ClonableFnBrand: ClonableFn, A: Ord> Ord
82 for Lazy<'a, OnceBrand, ClonableFnBrand, A>
83where
84 ApplyOnce<OnceBrand, A>: Ord,
85 ApplyClonableFn<'a, ClonableFnBrand, (), A>: Ord,
86{
87 fn cmp(
88 &self,
89 other: &Self,
90 ) -> std::cmp::Ordering {
91 self.0.cmp(&other.0)
92 }
93}
94
95impl<'a, OnceBrand: Once, ClonableFnBrand: ClonableFn, A: PartialEq> PartialEq
96 for Lazy<'a, OnceBrand, ClonableFnBrand, A>
97where
98 ApplyOnce<OnceBrand, A>: PartialEq,
99 ApplyClonableFn<'a, ClonableFnBrand, (), A>: PartialEq,
100{
101 fn eq(
102 &self,
103 other: &Self,
104 ) -> bool {
105 self.0 == other.0 && self.1 == other.1
106 }
107}
108
109impl<'a, OnceBrand: Once, ClonableFnBrand: ClonableFn, A: PartialOrd> PartialOrd
110 for Lazy<'a, OnceBrand, ClonableFnBrand, A>
111where
112 ApplyOnce<OnceBrand, A>: PartialOrd,
113 ApplyClonableFn<'a, ClonableFnBrand, (), A>: PartialOrd,
114{
115 fn partial_cmp(
116 &self,
117 other: &Self,
118 ) -> Option<std::cmp::Ordering> {
119 self.0.partial_cmp(&other.0)
120 }
121}
122
123impl<'b, OnceBrand: 'b + Once, CFB: 'b + ClonableFn, A: Semigroup<'b> + Clone> Semigroup<'b>
124 for Lazy<'b, OnceBrand, CFB, A>
125where
126 ApplyOnce<OnceBrand, A>: Clone,
127{
128 fn append<'a, ClonableFnBrand: 'a + 'b + ClonableFn>(
129 a: Self
130 ) -> ApplyClonableFn<'a, ClonableFnBrand, Self, Self>
131 where
132 Self: Sized,
133 'b: 'a,
134 {
135 <ClonableFnBrand as ClonableFn>::new(move |b: Self| {
136 Self::new(<CFB as ClonableFn>::new({
137 let a = a.clone();
138 move |_: ()| {
139 A::append::<ClonableFnBrand>(Lazy::force(a.clone()))(Lazy::force(b.clone()))
140 }
141 }))
142 })
143 }
144}
145
146impl<'b, OnceBrand: 'b + Once, CFB: 'b + ClonableFn, A: Monoid<'b> + Clone> Monoid<'b>
147 for Lazy<'b, OnceBrand, CFB, A>
148where
149 ApplyOnce<OnceBrand, A>: Clone,
150{
151 fn empty() -> Self {
152 Self::new(<CFB as ClonableFn>::new(move |_| <A as Monoid<'b>>::empty()))
153 }
154}
155
156impl<'a, OnceBrand: Once, CFB: ClonableFn, A: Clone> Defer<'a> for Lazy<'a, OnceBrand, CFB, A> {
157 fn defer<ClonableFnBrand: 'a + ClonableFn>(
158 f: ApplyClonableFn<'a, ClonableFnBrand, (), Self>
159 ) -> Self
160 where
161 Self: Sized,
162 {
163 Self::new(<CFB as ClonableFn>::new(move |_| Lazy::<'a, OnceBrand, CFB, A>::force(f(()))))
164 }
165}
166
167pub struct LazyBrand<OnceBrand: Once, ClonableFnBrand: ClonableFn>(OnceBrand, ClonableFnBrand);
168
169