F#泛型和铸造

kha*_*hik 3 generics f# casting

在阅读了所有相关的问题之后,我找不到我的问题的答案.写信给你,希望你很快就会回答,并且会毫不犹豫地判断我在这个领域缺乏知识.

我有一个体现函数定义的类型:

type FunctionDefinition<'a>(exec:int->(Data.Reader->'a)) =
    member x.Exec = exec
    member x.ReturnType = typeof<'a>
Run Code Online (Sandbox Code Playgroud)

正如你在这里看到的,exec应该是一个函数,它接受一个int参数并返回另一个函数,它接受一个Data.Reader参数并返回一个类型的值'a(这样一个令人筋疲力尽的短语!).这里的定义Data.Reader无关紧要.

另外,我有一个字典来保持string->FunctionDefinition对,如下:

let FUNCTIONS = new Generic.Dictionary<string, FunctionDefinition<obj>>()
Run Code Online (Sandbox Code Playgroud)

FunctionDefinition实例FUNCTIONS将持有几种类型的功能,这就是为什么它FunctionDefinition<obj>(我相信这是邪恶的根源,但我无法避免这种情况,所以我在这里).

然后我有一些函数要包装FunctionDefinition并放入FUNCTIONS:

/// Function definitions
let unchanged (id:int) = 
    let mutable last = null
    fun (reader:Data.Reader) -> 
        if last = null then
            false
        else
            let cur = reader.GetValue(id)
            let ret = last.Equals(cur)
            last <- cur
            ret

let changed (id:int) = 
    let un = unchanged id
    fun(reader:Data.Reader) ->
        not (un reader)

let dummyfortesting (id:int) = 
    fun(x) -> "yam-yam"
Run Code Online (Sandbox Code Playgroud)

我以为我可以将这些功能添加到我的字典中,但是......没有那种!以下代码:

FUNCTIONS.Add("unchanged", new FunctionDefinition<bool>(unchanged))
                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
FUNCTIONS.Add("changed", new FunctionDefinition<bool>(changed))
                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
FUNCTIONS.Add("dummy", new FunctionDefinition<string>(dummyfortesting))
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

给出明确的错误消息:

// The type 'obj' does not match the type 'bool'
// The type 'obj' does not match the type 'bool'
// The type 'obj' does not match the type 'string'
Run Code Online (Sandbox Code Playgroud)

而以下是真的:

typeof<bool>.isSubclassOf(typeof<obj>) // -> true
Run Code Online (Sandbox Code Playgroud)

这是不公平的,不是吗?


问题是

如何实例FUNCTIONS字典持有数FunctionDefinition<bool>,FunctionDefinition<string>实例?

或者除了FunctionDefinition为返回不同类型的函数保留泛型类型之外,还有其他解决方案吗?


一种解决方案是将所需类型作为参数传递给构造函数,FunctionDefinition如下所示:

type FunctionDefinition(typ:System.Type, exec:int->(Data.Reader->???)) =
    member x.Exec = exec
    member x.ReturnType = typ
Run Code Online (Sandbox Code Playgroud)

但目前还不清楚如何申报exec.

我希望我很清楚.

非常感谢.

您忠诚的,

KH

Tom*_*cek 5

您正在创建的字典需要保存相同类型的值.如果FunctionDefinition<'T>使用不同的类型参数创建两个值,则它们将是不同的类型,因此它们不能组合在单个字典中.

解决此问题的一种方法是定义非泛型接口并创建一个存储此接口值的字典(将由所有通用FunctionDefinition<'T>对象实现)

type IFunctionDefinition =
  abstract ReturnType : System.Type
  abstract Exec : int -> (Reader -> obj)

let dict = new Dictionary<string, IFunctionDefinition>()
Run Code Online (Sandbox Code Playgroud)

Exec函数必须返回obj,因为没有办法存储在(均相)dictionray功能后恢复的类型的信息.然后,您的具体类型可以实现接口:

type FunctionDefinition<'a>(exec:int->(Reader->'a)) = 
  member x.Exec = exec
  interface IFunctionDefinition with
    member x.ReturnType = typeof<'a>
    member x.Exec n = fun rdr -> box (exec n rdr)
Run Code Online (Sandbox Code Playgroud)

现在您可以将创建的函数定义添加到字典中,因为它们实现了公共接口:

let foo = FunctionDefinition<int>(fun _ _ -> 42)
dict.Add("foo", foo)
Run Code Online (Sandbox Code Playgroud)

另一种方法是使类型定义非通用.在使用字典中的函数来确定它们返回的值时,您需要进行一些动态类型测试.您可以通过使用区分联合作为返回类型来使其显式:

type ResultType =
  | String of string
  | Bool of bool
  // etc. for all supported return types
Run Code Online (Sandbox Code Playgroud)