generics - 当从一个泛型映射到另一个泛型时,为什么我必须破坏和重建泛型枚举的非泛型变体?

标签 generics types enums rust variant

这个问题在这里已经有了答案:





How to map a parametrized enum from a generic type to another?

(4 个回答)


2年前关闭。




我有一个泛型枚举,其中只有一个变体使用泛型类型。

当“转换”一个 ParseResult<T>ParseResult<U>编译器也强制我破坏非通用部分。非通用部分立即重新组装并以完全相同的方式返回。

没有代码重复有没有更优雅的解决方案?

#[derive(PartialEq, Debug)]
enum ParseResult<'a, T> {
    Success(T, &'a str),
    Failure(&'static str),
}

fn char<'a>(c: char) -> impl Fn(&'a str) -> ParseResult<'a, char> {
    move |input| match input.chars().next() {
        Some(candidate) if c == candidate => ParseResult::Success(candidate, &input[1..]),
        Some(_) => ParseResult::Failure("chars didn't match"),
        None => ParseResult::Failure("unexpected end of stream"),
    }
}

fn or<'a, T>(
    mut lhs: impl FnMut(&'a str) -> ParseResult<T>,
    mut rhs: impl FnMut(&'a str) -> ParseResult<T>,
) -> impl FnMut(&'a str) -> ParseResult<T> {
    move |input| match lhs(input) {
        ParseResult::Failure(_) => rhs(input),
        ok => ok,
    }
}

fn and<'a, T, U>(
    mut lhs: impl FnMut(&'a str) -> ParseResult<T>,
    mut rhs: impl FnMut(&'a str) -> ParseResult<U>,
) -> impl FnMut(&'a str) -> ParseResult<(T, U)> {
    move |input| match lhs(input) {
        ParseResult::Success(left, after) => match rhs(after) {
            ParseResult::Success(right, after) => ParseResult::Success((left, right), after),
            // Only explicit works:
            ParseResult::Failure(why) => ParseResult::Failure(why),
        },
        // Same as line as above, same goes here.
        ParseResult::Failure(why) => ParseResult::Failure(why),
    }
}

没用的东西,而不是两个 ::Failure行尾:
  • bad => bad,预期元组,找到类型参数 U
  • bad => bad as ParseResult<(T, U)>,
  • bad @ ParseResult::Failure(why) => bad,预期元组,找到类型参数 U

  • Playground

    最佳答案

    But the non-generic part is immediately reassembled and returned in exactly the same way. Isn't there a smarter/more elegant solution without the code duplication?



    看起来它以相同的方式重新组装,但这不是因为它从 ParseResult<T> 更改了类型至ParseResult<U> (或 ParseResult<(T, U)> 在你的情况下)。这些有不同的尺寸,所以ParseResult<T>::Failed(err)ParseResult<U>::Failed(err) 不一样.

    如果我们看 how the standard library handles this problem for Result::map ,您可以看到使用了相同的模式:
    match self {
         Ok(t) => Ok(op(t)),
         Err(e) => Err(e),
    }
    

    关于generics - 当从一个泛型映射到另一个泛型时,为什么我必须破坏和重建泛型枚举的非泛型变体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61498471/

    相关文章:

    python - 将字典的键和值从 `unicode` 转换为 `str` 的最快方法?

    c - 两个数组的交集 - C

    c# - 来自 Flags 枚举的随机值

    swift - 让或结构与枚举

    c# - List(T).ForEach 未使用 Xamarin 定义

    generics - 是否可以创建一个类型别名,该别名在函数的泛型类型上具有特征界限?

    c# - 确定类是否是具有多个泛型参数的类型的子类

    c# - 如何禁用泛型复杂类型字段的延迟加载?

    javascript - 为什么 TypeScript 使用对象属性赋值作为对象键并使用变量赋值作为函数参数?

    python - 方法的日志装饰器