对于初学者来说,我是函数式编程和F#的新手,因此我不知道是否可以做这样的事情。所以我们假设我们有这个功能:
let sum x y z = x + y + z
由于某种原因,我们希望使用列表中的元素作为参数来调用它。我的第一次尝试只是这样做:
//Seq.fold (fun f arg -> f arg) sum [1;2;3]
let rec apply f args =
match args with
| h::hs -> apply (f h) hs
| [] -> f
...不编译。使用静态类型系统确定f
的类型似乎是不可能的。
对于Haskell有identical question,唯一的解决方案是使用Data.Dynamic
来输出类型系统。我认为在F#中最接近它的是Dynamitey,但我不确定它是否合适。这段代码
let dynsum = Dynamitey.Dynamic.Curry(sum, System.Nullable<int>(3))
生成类型为dynsum
的{{1}}变量,并且无法调用此类型的对象,此外obj
不是.NET代理。
所以问题是,如何在F#中使用/不使用该库来完成?
答案 0 :(得分:3)
F#是一种静态类型的函数式语言,因此与F#一起使用的编程模式与您在LISP中使用的编程模式完全不同(实际上,它们也与您在Haskell中使用的编程模式不同)。因此,以您建议的方式使用函数不是您在正常的F#编程中所做的事情。
如果您对此功能考虑过一些情况,那么也许可以尝试询问原始问题,有人会帮您找到惯用的F#方法!
尽管如此,即使不推荐这样做,您也可以使用强大的.NET反射功能实现apply
功能。这很慢且不安全,但如果偶尔有用的话。
open Microsoft.FSharp.Reflection
let rec apply (f:obj) (args:obj list) =
let invokeFunc =
f.GetType().GetMethods()
|> Seq.find (fun m ->
m.Name = "Invoke" &&
m.GetParameters().Length = args.Length)
invokeFunc.Invoke(f, Array.ofSeq args)
代码查看函数的运行时类型,找到Invoke
方法并调用它。
let sum x y z = x + y + z
let res = apply sum [1;2;3]
let resNum = int res
最后,您需要将结果转换为int
,因为这不是静态的。