【发布时间】:2019-06-02 04:50:13
【问题描述】:
当尝试使用以下函数对一维变体数组进行排序时(这里的“变体”是指所有 Excel 类型,例如 bool、double(和日期)、字符串、各种错误...):
[<ExcelFunction(Category="test", Description="sort variants.")>]
let sort_variant ([<ExcelArgument(Description= "Array to sort.")>] arr : obj[]): obj[] =
arr
|> Array.sort
我收到以下错误:Error FS0001 The type 'obj' does not support the 'comparison' constraint. For example, it does not support the 'System.IComparable' interface,可能意味着所有 obj 类型都没有通用排序函数。
但 Excel 有一个自然的排序功能,我想效仿(至少大致如此)。例如双精度(和日期)
我的问题:在 F#/Excel-Dna 中对“变体”数组进行排序的惯用方法是什么? (我追求的是一个接受obj[] 并返回obj[] 的函数,没有别的,不是宏......)
我的(临时?)解决方案: 我创建了一个“有区别的联合”类型
type XLVariant = D of double | S of string | B of bool | NIL of string
(不确定是否需要 NIL,但它没有受到伤害。另外,在我的现实生活代码中,我添加了一个 DT of DateTime 实例,因为我需要区分日期和双精度)。
let toXLVariant (x : obj) : XLVariant =
match x with
| :? double as d -> D d
| :? string as s -> S s
| :? bool as b -> B b
| _ -> NIL "unknown match"
let ofXLVariant (x : XLVariant) : obj =
match x with
| D d -> box d
| S s -> box s
| B b -> box b
| NIL _ -> box ExcelError.ExcelErrorRef
[<ExcelFunction(Category="test", Description="sort variants.")>]
let sort_variant ([<ExcelArgument(Description= "Array to sort.")>] arr : obj[]): obj[] =
arr
|> Array.map toXLVariant
|> Array.sort
|> Array.map ofXLVariant
(为了简单起见,我忽略了Errors类型,但思路是一样的)
【问题讨论】:
-
我不太了解 Excel-Dna,无法编写正确的答案,但您的 DU 解决方案对我来说似乎是一个不错的解决方案:通过对 DU 案例进行排序以匹配 Excel 的自然排序函数(我不知道),你会因为没有那么多代码而获得很多好处。我会说你写的是一个很好的方法,我想不出改进它的方法。
-
由于类型信息已经是
obj值的一部分,如果您只实现IComparer<obj>并明确指定所需的顺序,可能会更简单。