假设您要编写一个函数“gen”,该函数生成一个带有由类型列表给出的签名的函数:
let gen (sig:Type list) = ....
let sig = [ typeof<int>; typeof<int[]>; typeof<float> ]
let func = gen sig
then func is of type: int -> int[] -> float -> unit
我想到了两种可能的解决方案:
a)使用Reflect Emit,但我不知道我们是否可以通过这种方式使IntelliSense正常工作? 反射Emit似乎创建了新的.net代码,IntelliSense可能看不到它,因此它可能无法在编译时验证代码。
b)使用类型提供者,但我担心太重,可能不实用。
c)使用泛型,如gen<'T1> (sig:Type list) : 'T2 -> unit
,这可能需要递归调用,但我没有想出如何执行此操作。
我更喜欢方法c),因为它是轻量级的,可以在编译时检查。或者有替代方法吗?
答案 0 :(得分:1)
请参阅MakeFunction
,http://msdn.microsoft.com/en-us/library/ee353497
比Reflection.Emit
更慢,但更容易使用,可能适合您的目的。
答案 1 :(得分:1)
你已经问过如何用一些给定的签名生成函数,但是问题忽略了关于函数体的观点。
假设你有办法设置这个主体,一个可能的解决方案可能看起来像这样(警告:因为内部使用反射,因此速度很慢):
module F =
type FST = Microsoft.FSharp.Reflection.FSharpType
type FSV = Microsoft.FSharp.Reflection.FSharpValue
let mkFunction (handler : obj list -> obj) : 'T =
if not (FST.IsFunction typeof<'T>) then failwith "Function type expected"
let rec chain args ty =
let dty, rty = FST.GetFunctionElements ty
let impl =
if FST.IsFunction rty then
fun o -> chain (o::args) rty
else
fun o -> handler(List.rev (o::args))
FSV.MakeFunction(ty, impl)
chain [] typeof<'T> :?> 'T
let f : int -> (int -> int) -> string =
F.mkFunction <|
fun [:? int as a; :? (int -> int) as f] ->
box (string (f a))
如果您想使用System.Type列表表示所需的签名 - 请向intellisence说再见