简体   繁体   English

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

[英]How to define an array of functions of different signature in F#

I would like to be able to use an array of functions along this line: 我希望能够沿着这条线使用一系列函数:

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

How could I express this idea in valid F# code? 如何用有效的F#代码表达这个想法?

The first thing is that you'll need to wrap the functions in StringFunc or DecimalFunc when putting them into the dictionary: 第一件事是,将函数放入字典时,需要将它们包装在StringFuncDecimalFunc

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

When you want to call the function, you'll need to handle the two cases separately. 当您要调用该函数时,需要分别处理这两种情况。 One issue here is that your two functions return different results. 这里的一个问题是您的两个函数返回不同的结果。 You cannot really do this directly, so when calling the function you'll have to return a boxed obj , or you'd have to define a new discriminated union that's either string or decimal. 您实际上不能直接直接执行此操作,因此在调用该函数时,您将必须返回一个装箱的obj ,或者您必须定义一个新的已区分字符串(字符串或十进制)。 The first option looks like this: 第一个选项如下所示:

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

Then you can use the call helper: 然后,您可以使用call助手:

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

The boxing means that you'll get back obj , but it's hard to say what would be the best way to handle this without knowing more about your specific situation. 拳击意味着您将获得obj ,但是很难说出在不了解您的具体情况的情况下处理此问题的最佳方法是什么。

From your code, I get the impression that the input type is always going to be the same (int in the example), in order to be able to call any column without knowing its type. 从您的代码中,我得到的印象是,输入类型将始终是相同的(在示例中为int),以便能够在不知道其类型的情况下调用任何列。

If so, you might want to use a DU for the return type, and not for the function type. 如果是这样,则可能要对返回类型而不是函数类型使用DU。 This way you'll get the calling behaviour you want. 这样,您将获得所需的呼叫行为。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM