1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use crate::{Cons, HList, Nil};
use super::Extend;
/// Flattens one level of nesting in a heterogenous list of heterogenous lists.
///
/// This is useful when you have a heterogenous list of heterogenous lists
/// and you want to remove one level of indirection.
pub trait Flatten: HList {
/// Flattened heterogenous list.
type Output: HList;
/// Flattens a heterogenous list of heterogenous lists, removing one level of indirection.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// use hlist2::{hlist, ops::Flatten};
///
/// let data = hlist![hlist![1, 2.0, true, "hello world"], hlist![5, 6.0]];
/// let flattened = data.flatten();
/// assert_eq!(flattened, hlist![1, 2.0, true, "hello world", 5, 6.0]);
/// ```
///
/// Flattening only removes one level of nesting at a time:
///
/// ```
/// use hlist2::{hlist, ops::Flatten};
///
/// let d3 = hlist![
/// hlist![hlist![0, 1], hlist![2, 3]],
/// hlist![hlist![4, 5], hlist![6, 7]],
/// hlist![hlist![8, 9]],
/// ];
///
/// let d2 = d3.flatten();
/// assert_eq!(d2, hlist![hlist![0, 1], hlist![2, 3], hlist![4, 5], hlist![6, 7], hlist![8, 9]]);
///
/// let d1 = d3.flatten().flatten();
/// assert_eq!(d1, hlist![0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
/// ```
///
/// Here we see that `flatten()` does not perform a “deep” flatten. Instead, only one level of nesting is removed.
/// That is, if you `flatten()` a three-dimensional list, the result will be two-dimensional and not one-dimensional.
/// To get a one-dimensional structure, you have to `flatten()` again.
fn flatten(self) -> Self::Output;
}
impl Flatten for Nil {
type Output = Self;
fn flatten(self) -> Self::Output {
self
}
}
impl<Head, Tail> Flatten for Cons<Head, Tail>
where
Head: Extend,
Tail: Flatten,
{
type Output = Head::Output<Tail::Output>;
fn flatten(self) -> Self::Output {
let Cons(head, tail) = self;
let tail = tail.flatten();
head.extend(tail)
}
}