How to match a parameterized enumeration from a generic type to another?

If I have a type type MyEnum<T>, how can I match it in cases when not every parameter is parameterized?

For example, I would like to convert from MyEnum<u32>to MyEnum<String>:

enum MyEnum<T> {
    B,
    C,
    D(T),
}

fn trans(a: MyEnum<u32>) -> MyEnum<String> {
    match a {
        MyEnum::D(i) => MyEnum::D(i.to_string()),
        other_cases => other_cases,
    }
}

fn main() {}

This fails:

error[E0308]: match arms have incompatible types
  --> src/main.rs:8:9
   |
8  |         match a {
   |         ^ expected struct `std::string::String`, found u32
   |
   = note: expected type `MyEnum<std::string::String>`
   = note:    found type `MyEnum<u32>`
note: match arm with an incompatible type
  --> src/main.rs:10:28
   |
10 |             other_cases => other_cases,
   |                            ^^^^^^^^^^^

Instead of a line, other_cases => other_casesI tried this, also unsuccessfully:

other_cases => {
    let o: MyEnum<String> = other_cases;
    o
}
+5
source share
4 answers
macro_rules! partial_enum {
    ($name: ident, $some: ident, $($none: ident),+) => {
        #[derive(Debug)]
        enum $name<T> {
            $some(T),
            $($none),+
        }
        impl<T> $name<T> {
            fn convert<U>(self) -> Result<$name<U>, T> {
                match self {
                    $name::$some(x) => Err(x),
                    $($name::$none => Ok($name::$none)),+
                }
            }
        }
    }
}
partial_enum!(MyEnum, D, B, C);
fn trans(a: MyEnum<u32>) -> MyEnum<String> {
    let a_split: Result<MyEnum<String>, u32> = a.convert();
    match a_split {
        Ok(is_none) => is_none,
        Err(not_none) => MyEnum::D(not_none.to_string()),
    }
}
fn main() {
    println!("{:?}", trans(MyEnum::D(13)));
}
+2
source

I would create a method mapfor your listing:

#[derive(Debug)]
enum MyEnum<T> {
    B,
    C,
    D(T),
}

impl<T> MyEnum<T> {
    fn map<F, U>(self, f: F) -> MyEnum<U>
    where
        F: FnOnce(T) -> U,
    {
        use MyEnum::*;

        match self {
            B => B,
            C => C,
            D(x) => D(f(x)),
        }
    }
}

fn main() {
    let answer = MyEnum::D(42);
    let answer2 = answer.map(|x| x.to_string());
    println!("{:?}", answer2);
}

This is similar to existing methods mapsuch as Option::map.

+8
source

, :

enum MyEnum<T> {
    B,
    C,
    D(T),
}

fn trans(a: MyEnum<u32>) -> MyEnum<String> {
    match a {
        MyEnum::D(i) => MyEnum::D(i.to_string()),
        MyEnum::B => MyEnum::B,
        MyEnum::C => MyEnum::C
    }
}

fn main() {
}

, .

+5

(, ++) Duck Typing: , , , . .

Rust - - , , B in MyEnum<u32> MyEnum<String> , , .


:

  • build.rs script
  • ,
  • , , .

:

enum MyEnumImpl {
    A,
    B,
    C,
}

enum MyEnum<T> {
    Independent(MyEnumImpl),
    Dependent(T),
}

, .

+3
source

All Articles