1use core::marker::PhantomData;
4
5use crate::higher::Higher;
6
7pub trait AndThen<B>: Higher {
15 fn and_then<F>(self, f: F) -> Self::Target<B>
17 where
18 F: FnMut(Self::Param) -> Self::Target<B>;
19}
20
21#[macro_export]
24macro_rules! and_then_flat_map {
25 ($name:ident<$( $t:tt ),+>) => {
26 impl<B, $( $t ),+> $crate::and_then::AndThen<B> for $name<$( $t ),+> {
27 #[inline]
28 fn and_then<F>(self, f: F) -> Self::Target<B>
29 where
30 F: FnMut(Self::Param) -> Self::Target<B>,
31 {
32 $crate::flatmap::FlatMap::flat_map(self, f)
33 }
34 }
35 };
36 ($name:ident<$( $t:tt ),+>, $ct:tt $(+ $dt:tt )*) => {
37 impl<B:$ct $(+ $dt )*, $( $t ),+> $crate::and_then::AndThen<B> for $name<$( $t ),+> {
38 #[inline]
39 fn and_then<F>(self, f: F) -> Self::Target<B>
40 where
41 F: FnMut(Self::Param) -> Self::Target<B>,
42 {
43 $crate::flatmap::FlatMap::flat_map(self, f)
44 }
45 }
46 };
47}
48
49impl<A, B> AndThen<B> for PhantomData<A> {
50 fn and_then<F>(self, _f: F) -> PhantomData<B>
51 where
52 F: FnMut(A) -> PhantomData<B>,
53 {
54 PhantomData
55 }
56}
57
58and_then_flat_map!(Option<T>);
59and_then_flat_map!(Result<T, E>);
60
61if_std! {
62 use std::boxed::Box;
63 use std::collections::*;
64 use std::hash::Hash;
65 use std::vec::Vec;
66 use crate::flatmap::FlatMap;
67
68 and_then_flat_map!(Vec<T>);
69 and_then_flat_map!(LinkedList<T>);
70 and_then_flat_map!(VecDeque<T>);
71 and_then_flat_map!(Box<T>);
72 and_then_flat_map!(BinaryHeap<T>, Ord);
73 and_then_flat_map!(BTreeSet<T>, Ord);
74 and_then_flat_map!(HashSet<T>, Hash + Eq);
75
76 impl<A, B, K: Hash + Eq> AndThen<B> for HashMap<K, A> {
77 #[inline]
78 fn and_then<F>(self, f: F) -> HashMap<K, B>
79 where
80 F: FnMut(A) -> HashMap<K, B>,
81 {
82 self.flat_map(f)
83 }
84 }
85}