gpt4 book ai didi

f# 从函数返回部分函数

转载 作者:行者123 更新时间:2023-11-30 23:48:09 26 4
gpt4 key购买 nike

虽然将部分函数传递给另一个函数很简单,但如何从函数返回不同签名的部分函数?

这是我正在尝试的基本代码,然后进行了各种尝试以使其正常工作:

type InitData() =
static member arrayIntAsc count = [|1..count|]
static member seqIntAsc count = {1..count}
static member listIntAsc count = [1..count]
(*more diverse signatures*)

module x =
let getInitDataFun (initData:string) =
match initData.ToLower() with
| "arrayintasc" -> InitData.arrayIntAsc
| "seqintasc" -> InitData.seqIntAsc
| "listintasc" -> InitData.listIntAsc
(*more diverse signatures*)
| _ -> failwithf "InitData function %s not recognized" initData
  1. 尝试以各种方式强制使用通用返回签名,但 F# 3.0 始终将 getInitDataFun 返回签名强制为第一个匹配项的签名:

    let getInitDataFun (initData:string) : 'a -> 'b  = ...
    let getInitDataFun (initData:string) : _ -> _ = ...
    let getInitDataFun (initData:string) : int -> #(int seq) = ...
    let getInitDataFun (initData:string) : int -> #('a seq) = ...
    (*even if I could get (int -> #(int seq)) to work, I would like to return
    signatures not in this pattern too*)
  2. 尝试装箱/拆箱:

    | "arrayintasc" -> box InitData.arrayIntAsc

    这会编译,但拆箱尝试会引发运行时错误:

    Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'RangeInt32@4819-2' to type 'System.Collections.Generic.IEnumerable`1[System.Object]'

  3. 尝试将部分函数作为引号返回,但遇到了类似的问题。如果我返回键入的引号,则在返回不同的 Expr 签名时会遇到同样的问题。我可以返回未类型化的引号,但我必须在调用方知道返回的未类型化表达式的签名。

  4. 考虑过反射,但基本上是相同的问题,需要在调用时知道实际签名。

  5. 也尝试以各种方式向上转换部分函数。

最佳答案

最好的办法是将静态成员更改为全部返回相同的类型:

type InitData() =
static member arrayIntAsc count = seq [|1..count|]
static member seqIntAsc count = {1..count}
static member listIntAsc count = seq [1..count]

或者用一个执行转换的函数包装它们:

let getInitDataFun (initData:string) =
let asSeq f x = f x :> seq<_>
match initData.ToLower() with
| "arrayintasc" -> asSeq InitData.arrayIntAsc
| "seqintasc" -> InitData.seqIntAsc
| "listintasc" -> asSeq InitData.listIntAsc

可以使其通用:

let getInitDataFun<'T when 'T :> seq<int>> (initData:string) : (int -> 'T) =
match initData.ToLower() with
| "arrayintasc" -> (box >> unbox) InitData.arrayIntAsc
| "seqintasc" -> (box >> unbox) InitData.seqIntAsc
| "listintasc" -> (box >> unbox) InitData.listIntAsc

但如果预期返回类型错误,它会产生运行时异常:

let f = getInitDataFun "arrayintasc"
let x : int list = f 10 //BOOM!

关于f# 从函数返回部分函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11106737/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com