1use crate::{
4 functions::map,
5 hkt::{Apply, Brand, Brand1, Kind, Kind1},
6 impl_brand,
7 typeclasses::{Apply as TypeclassApply, ApplyFirst, ApplySecond, Bind, Functor, Pure},
8};
9
10impl_brand!(OptionBrand, Option, Kind1, Brand1, (A));
11
12impl Pure for OptionBrand {
13 fn pure<A>(a: A) -> Apply<Self, (A,)>
20 where
21 Self: Kind<(A,)>,
22 {
23 <Self as Brand<_, _>>::inject(Some(a))
24 }
25}
26
27impl Functor for OptionBrand {
28 fn map<F, A, B>(f: F) -> impl Fn(Apply<Self, (A,)>) -> Apply<Self, (B,)>
37 where
38 Self: Kind<(A,)> + Kind<(B,)>,
39 F: Fn(A) -> B,
40 {
41 move |fa| <Self as Brand<_, _>>::inject(<Self as Brand<_, _>>::project(fa).map(&f))
42 }
43}
44
45impl TypeclassApply for OptionBrand {
46 fn apply<F, A, B>(ff: Apply<Self, (F,)>) -> impl Fn(Apply<Self, (A,)>) -> Apply<Self, (B,)>
57 where
58 Self: Kind<(F,)> + Kind<(A,)> + Kind<(B,)>,
59 F: Fn(A) -> B,
60 Apply<Self, (F,)>: Clone,
61 {
62 move |fa| match (<Self as Brand<_, _>>::project(ff.to_owned()), &fa) {
63 (Some(f), _) => map::<Self, F, _, _>(f)(fa),
64 _ => <Self as Brand<_, _>>::inject(None::<B>),
65 }
66 }
67}
68
69impl ApplyFirst for OptionBrand {
70 fn apply_first<A, B>(fa: Apply<Self, (A,)>) -> impl Fn(Apply<Self, (B,)>) -> Apply<Self, (A,)>
81 where
82 Self: Kind<(A,)> + Kind<(B,)>,
83 Apply<Self, (A,)>: Clone,
84 {
85 move |fb| {
86 <Self as Brand<_, (A,)>>::inject(
87 match (
88 <Self as Brand<_, _>>::project(fa.to_owned()),
89 <Self as Brand<_, (B,)>>::project(fb),
90 ) {
91 (Some(a), Some(_)) => Some(a),
92 _ => None,
93 },
94 )
95 }
96 }
97}
98
99impl ApplySecond for OptionBrand {
100 fn apply_second<A, B>(_fa: Apply<Self, (A,)>) -> impl Fn(Apply<Self, (B,)>) -> Apply<Self, (B,)>
111 where
112 Self: Kind<(A,)> + Kind<(B,)>,
113 Apply<Self, (A,)>: Clone,
114 {
115 move |fb| {
116 <Self as Brand<_, (B,)>>::inject(
117 match (
118 <Self as Brand<_, (A,)>>::project(_fa.to_owned()),
119 <Self as Brand<_, (B,)>>::project(fb),
120 ) {
121 (Some(_), Some(a)) => Some(a),
122 _ => None,
123 },
124 )
125 }
126 }
127}
128
129impl Bind for OptionBrand {
130 fn bind<F, A, B>(ma: Apply<Self, (A,)>) -> impl Fn(F) -> Apply<Self, (B,)>
139 where
140 Self: Kind<(A,)> + Kind<(B,)> + Sized,
141 F: Fn(A) -> Apply<Self, (B,)>,
142 Apply<Self, (A,)>: Clone,
143 {
144 move |f| {
145 <Self as Brand<_, _>>::inject(
146 <Self as Brand<_, _>>::project(ma.to_owned())
147 .and_then(|a| -> Option<B> { <Self as Brand<_, _>>::project(f(a)) }),
148 )
149 }
150 }
151}