Are there any ways to recursively flatten tuples?

后端 未结 2 1618
醉梦人生
醉梦人生 2021-01-19 09:28

In Rust, is there any way to use traits and impls to (recursively) flatten tuples?

If it helps, something that works with N nested pairs is

2条回答
  •  遥遥无期
    2021-01-19 10:04

    Maybe for certain small definitions of "flatten", but realistically not really.

    Start with the most specific implementation:

    trait FlattenTuple {
        fn into_flattened(self) -> (u8, u8, u8);
    }
    
    impl FlattenTuple for (u8, (u8, u8)) {
        fn into_flattened(self) -> (u8, u8, u8) {
            (self.0, (self.1).0, (self.1).1)
        }
    }
    

    Then make it a bit more generic:

    trait FlattenTuple {
        type Output;
        fn into_flattened(self) -> Self::Output;
    }
    
    impl FlattenTuple for (A, (B, C)) {
        type Output = (A, B, C);
    
        fn into_flattened(self) -> Self::Output {
            (self.0, (self.1).0, (self.1).1)
        }
    }
    

    And then repeat for every possible permutation:

    impl FlattenTuple for ((A, B), C, (D, (E, F))) {
        type Output = (A, B, C, D, E, F);
    
        fn into_flattened(self) -> Self::Output {
            ((self.0).0, (self.0).1, self.1, (self.2).0, ((self.2).1).0, ((self.2).1).1)
        }
    }
    

    These two implementations cover your two cases.

    However, you'd then have to enumerate every input type you'd like, probably via code generation. There's no way I'm aware of to "inspect" the input type and then "splice" it into the output type.

    You can even try to write something somewhat recursive:

    impl FlattenTuple for (A, B)
        where A: FlattenTuple,
              B: FlattenTuple,
    {
        type Output = (C, D, E, F);
    
        fn into_flattened(self) -> Self::Output {
            let (a, b) = self;
            let (c, d) = a.into_flattened();
            let (e, f) = b.into_flattened();
    
            (c, d, e, f)
        }
    }
    

    But this will quickly run into base-case issues: the terminal 42 doesn't implement FlattenTuple, and if you try to impl FlattenTuple for T you will hit conflicting trait implementations.

提交回复
热议问题