我希望能够在这一行中使用一系列函数:
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#代码表达这个想法?
答案 0 :(得分:4)
首先,当将这些函数放入字典时,您需要将函数包装在StringFunc
或DecimalFunc
中:
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