Rust 当转换可能失败时,如何选择性地规范化值?

Rust 当转换可能失败时,如何选择性地规范化值?,rust,Rust,我希望定义一个函数,该函数检查两个值,并可选地将其中一个值更改为匹配类型。其动机是为数学公式执行自动转换。我的规则是: 两者都是i64,别管了 两者都是f64,别管了 一个是i64,一个是f64,将i64更改为f64 其他类型的其他规则 例如: fn normalize(arg1: Option<MyValue>, arg2: Option<MyValue>) -> (Option<MyValue>, Option<MyValue>) {

我希望定义一个函数,该函数检查两个值,并可选地将其中一个值更改为匹配类型。其动机是为数学公式执行自动转换。我的规则是:

  • 两者都是i64,别管了
  • 两者都是f64,别管了
  • 一个是
    i64
    ,一个是
    f64
    ,将
    i64
    更改为
    f64
  • 其他类型的其他规则
例如:

fn normalize(arg1: Option<MyValue>, arg2: Option<MyValue>) -> (Option<MyValue>, Option<MyValue>) {
    unimplemented!();
}
trait MapType {
    type Output;
}

impl MapType for f64 {
    type Output i64;
}

impl MapType for bool {
    type Output u8;
}

您可以将具有关联类型的trait视为在类型之间映射的编译时函数。例如:

fn normalize(arg1: Option<MyValue>, arg2: Option<MyValue>) -> (Option<MyValue>, Option<MyValue>) {
    unimplemented!();
}
trait MapType {
    type Output;
}

impl MapType for f64 {
    type Output i64;
}

impl MapType for bool {
    type Output u8;
}
对于可能需要的每个类型,可以实现
MapType
,以提供到唯一
输出的映射

您的案例是关于类型对的,您可以通过添加一个参数来扩展上述想法:

trait Normalize<T>: Sized {
    type Norm;
}
为您想要的类型对实施它:

impl Normalize<u32> for f64 {
    type Norm = f64;
}

impl Normalize<f64> for u32 {
    type Norm = f64;
}


你很快就会意识到我在这里有点作弊,用了
u32
而不是
u64
。那是因为。如果你需要这些类型对,那么你仍然可以保持我所概述的方法,但是你需要定义你自己版本的
TryInto
TryFrom
traits,并为你需要的所有类型对自己实现它们。

你能做一个包含所有可接受类型的枚举吗,然后在枚举上使用一个转换运算符进行规范化?为了简单起见,我没有显示额外的参数,运算符。每个运算符的转换不相同。将arg1视为左值,arg2视为右值,它们之间有一个二进制运算符。此规范化函数将附加到运算符枚举。转换失败。。。比如什么?这个问题是基于意见的,我投票决定就此结束。挑一个试试看。如果行得通,那太好了。如果没有,或者使用起来很烦人,选择另一个。如果你用尽了你的选项列表,问一个新问题寻找替代方案。因为这个问题的当前形式似乎离题了,你可能希望查看其他参考资料。欢迎在或上进行更多开放式问题和讨论。
impl<X> Normalize<X> for X {
    type Norm = X;
}
fn normalize<A, B>(arg1: Option<A>, arg2: Option<B>) -> (Option<A::Norm>, Option<A::Norm>) 
where
    A: Normalize<B>,
    A::Norm: TryFrom<B>,
{
    (
        arg1.and_then(|a| a.try_into().ok()),
        arg2.and_then(|b| b.try_into().ok())
    )
}

fn main() {
    println!("{:?}", normalize(Some(1u32), Some(1u32))); // (Some(1), Some(1))
    println!("{:?}", normalize(Some(1f64), Some(1u32))); // (Some(1.0), Some(1.0))
    println!("{:?}", normalize(Some(1u32), Some(1f64))); // (Some(1.0), Some(1.0))
    println!("{:?}", normalize(Some(1f64), Some(1f64))); // (Some(1.0), Some(1.0))
}