如何在F#中定义不同签名的函数数组

时间:2015-08-20 16:29:23

标签: arrays function f#

我希望能够在这一行中使用一系列函数:

type SomeFunc =
| StringFunc  of (int -> string)
| DecimalFunc of (int -> decimal)

let dataCols = Dict<string, SomeFunc>()
dataCols["A"] <- fun x -> sprintf "%d" x
dataCols["B"] <- fun x -> decimal x

// would want to have:
(dataCols["A"] 0) // "0"
(dataCols["B"] 0) // 0M

我怎么能用有效的F#代码表达这个想法?

2 个答案:

答案 0 :(得分:4)

首先,当将这些函数放入字典时,您需要将函数包装在StringFuncDecimalFunc中:

let dataCols = Dictionary<string, SomeFunc>()
dataCols["A"] <- StringFunc(fun x -> sprintf "%d" x)
dataCols["B"] <- DecimalFunc(fun x -> decimal x)

当您想要调用该功能时,您需要分别处理这两种情况。这里的一个问题是你的两个函数返回不同的结果。你不能直接这样做,所以在调用函数时你必须返回一个盒装obj,或者你必须定义一个新的区别联合,它是字符串或小数。第一个选项如下所示:

let call func arg = 
  match func with
  | StringFunc f -> box (f arg)
  | DecimalFunc f -> box (f arg)

然后您可以使用call帮助程序:

call (dataCols["A"]) 0
call (dataCols["B"]) 0

拳击意味着你会回来obj,但很难说在不了解你的具体情况的情况下,最好的办法是什么。

答案 1 :(得分:2)

从您的代码中,我得到的印象是输入类型总是相同的(示例中为int),以便能够在不知道其类型的情况下调用任何列。

如果是这样,您可能希望将DU用于 return 类型,而不是函数类型。这样你就可以得到你想要的召唤行为。

type ColumnValue =
| StringValue of string
| DecimalValue of decimal

let dataCols = Dictionary<string, (int -> ColumnValue)>()
dataCols.["A"] <- fun x -> StringValue (sprintf "%d" x)
dataCols.["B"] <- fun x -> DecimalValue (decimal x)

// what you get
dataCols.["A"] 0 // (StringValue "0")

match (dataCols.["A"] 0) with
| StringValue s -> printf "%s" s
| DecimalValue d -> printf "%M" d