1use std::sync::Arc;
6
7#[derive(Clone)]
23pub struct Maybe<T> {
24 r: Arc<Option<T>>,
25}
26
27impl<T: Clone + 'static> Maybe<T> {
28 pub fn option(&self) -> Option<T> {
29 self.r.as_ref().clone()
30 }
31 pub fn unwrap(&self) -> T {
32 self.r.as_ref().clone().unwrap()
33 }
34 pub fn or(&self, val: T) -> T {
35 self.r.as_ref().clone().unwrap_or(val)
36 }
37}
38
39impl<T: 'static> From<T> for Maybe<T> {
40 fn from(r: T) -> Self {
41 Maybe::just(Some(r))
42 }
43}
44
45impl<T: 'static> Maybe<T> {
46 pub fn just(r: Option<T>) -> Maybe<T> {
47 Maybe { r: Arc::new(r) }
48 }
49 pub fn of(r: Option<T>) -> Maybe<T> {
50 Maybe::just(r)
51 }
52 pub fn val(r: T) -> Maybe<T> {
53 Maybe::just(Some(r))
54 }
55
56 pub fn present(&self) -> bool {
57 match self.r.as_ref() {
58 Some(_x) => true,
59 None => false,
60 }
61 }
62 pub fn null(&self) -> bool {
63 match self.r.as_ref() {
64 Some(_x) => false,
65 None => true,
66 }
67 }
68 pub fn let_do<F>(&self, func: F)
69 where
70 F: FnOnce(&T),
71 {
72 match self.r.as_ref() {
73 Some(_x) => func(&_x),
74 None => (),
75 }
76 }
77
78 pub fn fmap<F, G>(&self, func: F) -> Maybe<G>
79 where
80 F: FnOnce(&Option<T>) -> Maybe<G>,
81 {
82 func(self.r.as_ref())
83 }
84 pub fn map<F, G>(&self, func: F) -> Maybe<G>
85 where
86 F: FnOnce(&Option<T>) -> Option<G>,
87 G: 'static,
88 {
89 Maybe::just(func(self.r.as_ref()))
90 }
91 pub fn bind<F, G>(&self, func: F) -> Maybe<G>
92 where
93 F: FnOnce(&Option<T>) -> Option<G>,
94 G: 'static,
95 {
96 self.map(func)
97 }
98 pub fn then<F, G>(&self, func: F) -> Maybe<G>
99 where
100 F: FnOnce(&Option<T>) -> Option<G>,
101 G: 'static,
102 {
103 self.map(func)
104 }
105 pub fn chain<F, G>(&self, func: F) -> Maybe<G>
106 where
107 F: FnOnce(&Option<T>) -> Maybe<G>,
108 {
109 self.fmap(func)
110 }
111 pub fn ap<F, G>(&self, maybe_func: &Maybe<F>) -> Maybe<G>
112 where
113 F: FnOnce(&Option<T>) -> Option<G> + Clone + 'static,
114 G: 'static,
115 {
116 maybe_func.chain(|f| self.map(f.clone().unwrap()))
117 }
118}
119
120#[test]
121fn test_maybe_present() {
122 assert_eq!(false, Maybe::just(None::<bool>).present());
123 assert_eq!(true, Maybe::val(true).present());
124
125 assert_eq!(true, Maybe::just(None::<bool>).null());
126 assert_eq!(false, Maybe::val(true).null());
127
128 let mut val;
129
130 val = false;
131 Maybe::just(None::<bool>).let_do(|x| val = *x);
132 assert_eq!(false, val);
133
134 val = false;
135 Maybe::val(true).let_do(|x| val = *x);
136 assert_eq!(true, val);
137}
138#[test]
139fn test_maybe_flatmap() {
140 assert_eq!(
141 false,
142 Maybe::val(true)
143 .fmap(|x| return Maybe::val(!x.unwrap()))
144 .unwrap()
145 );
146 assert_eq!(
147 true,
148 Maybe::val(false)
149 .fmap(|x| return Maybe::val(!x.unwrap()))
150 .unwrap()
151 );
152
153 assert_eq!(
154 false,
155 Maybe::val(true).map(|x| return Some(!x.unwrap())).unwrap()
156 );
157 assert_eq!(
158 true,
159 Maybe::val(false).map(|x| return Some(!x.unwrap())).unwrap()
160 );
161
162 assert_eq!(
163 true,
164 Maybe::val(1)
165 .ap(&Maybe::val(|x: &Option<i16>| if x.unwrap() > 0 {
166 return Some(true);
167 } else {
168 return Some(false);
169 }))
170 .unwrap()
171 );
172}
173#[test]
174fn test_maybe_unwrap() {
175 assert_eq!(false, Maybe::just(None::<bool>).or(false));
176 assert_eq!(true, Maybe::val(true).or(false));
177 use std::panic;
178
179 let none_unwrap = panic::catch_unwind(|| {
180 Maybe::just(None::<bool>).unwrap();
181 });
182 assert_eq!(true, none_unwrap.is_err());
183 assert_eq!(true, Maybe::val(true).unwrap());
184
185 assert_eq!(
186 true,
187 match Maybe::val(true).option() {
188 None => false,
189 Some(_x) => true,
190 }
191 );
192 assert_eq!(
193 false,
194 match Maybe::just(None::<bool>).option() {
195 None => false,
196 Some(_x) => true,
197 }
198 );
199}