【问题标题】:Comparing two objects with default IComparable implementation with F# Reflection使用 F# 反射将两个对象与默认 IComparable 实现进行比较
【发布时间】:2020-04-04 09:07:24
【问题描述】:

给定 F# 中的两个对象,有没有办法使用它们的 IComparable 方法来比较它们,假设它们都是相同的子类型并且 IComparable 是针对它们的公共子类型实现的。

我想用伪代码实现什么:

    let tycompare (o1 : obj) (o2 : obj) : int option =
        let (ty1, ty2) = (o1.GetType(), o2.GetType())
        if ty1 <> ty2 then
            None
        else
            if IComparable is implemented on ty1 then
                o1.CompareTo(o2) |> Some
            else
                None

我知道这个post,但我认为这对直接回答我的问题没有帮助。

【问题讨论】:

    标签: reflection f# icomparable


    【解决方案1】:

    您也可以使用Option.bind 更简洁地编写此代码,但这非常适合模式匹配。

    我们可以定义一个active pattern 来匹配IComparable

    let (|IsComparable|) (obj : obj) = 
        match obj with
        | :? IComparable as comparable -> Some(comparable)
        | _ ->  None
    

    F# 允许您在 let 绑定中使用活动模式,从而更清楚地传达函数的意图。

    let compare (IsComparable o1) (IsComparable o2) =        
        match (o1, o2) with
        | (Some o1, Some o2) when 
            o1.GetType() = o2.GetType() -> Some(o1.CompareTo(o2))
        | _ -> None
    

    这也可以被压缩(没有活动模式 - @kaefer):

    let compare (o1 : obj) (o2: obj) = 
        match (o1, o2 ) with
        | (:? System.IComparable as o1), (:? System.IComparable as o2) when 
            o1.GetType() = o2.GetType() -> Some(o1.CompareTo(o2))
        | _ -> None
    

    【讨论】:

    • 您也可以不使用活动模式,而是使用as patterns| :? System.IComparable as i1, (:? System.IComparable as i2) when ...
    • @kaefer 我已经添加了just模式版本。我对活动模式有明确的偏见:)
    • 谢谢阿斯蒂。它适用于实现 IComparable 的基本类型,这正是我所要求的,但它不适用于诸如 double[]、string[] 之类的类型......我猜这些类型更像是“种类”'T when 'T : comparison .我们如何扩展您的解决方案以涵盖这些情况?我试过addin | (:? Comparison&lt;_&gt; as c1), (:? Comparison&lt;_&gt; as c2) -&gt; ...(没有类型参数,因为我没有)但它不起作用。
    • 您认为将双精度数组与另一个数组进行比较的结果应该是什么?
    • 1- 谢谢@Asti。一个简单的partial order 关系就可以了。就像我们可以考虑(ASCII)字符串、字符数组的“自然”顺序一样,其中例如"abc" > "abb" and "abca" > "abc" 但是 "abc" > "abbd",我们可以类似地比较任何数组(假设它们的元素的集合是有序的)例如[| 10个; 20; 30 |] > [| 10个; 20; 29 |] 和 [| 10个; 20; 30; -100 |] > [| 10个; 20; 30 |] 但 [| 10个; 20; 30 |] > [| 10个; 20; 29; 100 |] 等... (由于 cmets 的大小限制,我必须将其他 cmets 分解为几个较小的子部分).
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多