f#从函数返回部分函数
虽然将一个部分函数传递给另一个函数很简单,但是如何从一个函数返回具有不同签名的部分函数呢 以下是我正在尝试的基本代码,然后是各种尝试使其正常工作:f#从函数返回部分函数,f#,F#,虽然将一个部分函数传递给另一个函数很简单,但是如何从一个函数返回具有不同签名的部分函数呢 以下是我正在尝试的基本代码,然后是各种尝试使其正常工作: type InitData() = static member arrayIntAsc count = [|1..count|] static member seqIntAsc count = {1..count} static member listIntAsc count = [1..count] (*more
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
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*)
| "arrayintasc" -> box InitData.arrayIntAsc
这会编译,但取消装箱尝试会引发运行时错误:
未处理的异常:System.InvalidCastException:无法强制转换类型为的对象RangeInt32@4819-2'
输入'System.Collections.Generic.IEnumerable`1[System.Object]'
我想这是你想要的
type InitData() =
static member arrayIntAsc count = [|1..count|]
static member seqIntAsc count = {1..count}
static member listIntAsc count = [1..count]
(*more diverse signatures*)
let getInitDataFun (initData:string) : obj =
match initData.ToLower() with
| "arrayintasc" -> box InitData.arrayIntAsc
| "seqintasc" -> box InitData.seqIntAsc
| "listintasc" -> box InitData.listIntAsc
(*more diverse signatures*)
| _ -> failwithf "InitData function %s not recognized" initData
let a = ((getInitDataFun "arrayintasc") :?> int->int[]) 20
printfn "%A" a
或者我不清楚您在问什么。您最好将静态成员更改为所有返回相同类型:
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
你能解释一下你为什么要这样做吗?您希望调用方如何使用
getInitDataFun
?也许我不太清楚,我不想知道调用方的签名。您的解决方案需要知道返回的签名才能进行向下转换。@Jack:F#是一种强静态类型语言——调用者需要知道它在调用什么。@ildjam:yep。我认为我解决了正确解决问题的方法是将多样性签名的函数向前线程化,而不是试图返回它们。我的初衷和问题是命令式思维的残余。
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!