Сравнение двух объектов с реализацией по умолчанию IComparable с F # Reflection - PullRequest
1 голос
/ 04 апреля 2020

Учитывая два объекта в 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

Мне известно об этом сообщении , но я не думаю, что это помогает ответить на мой вопрос напрямую.

1 Ответ

4 голосов
/ 04 апреля 2020

Вы также можете написать это более кратко с помощью Option.bind, но это хорошо подходит для сопоставления с образцом.

Мы можем определить активный образец для сопоставления 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
...