我正在使用函数2x ^ 2 + y ^ 2,在我的代码中定义为:
fx = fun x y -> (2 * (pown x 2)) + (pown y 2)
我想知道是否可以递归地应用x和y分量?
当前,如果我愿意
let f1 = fx 0.0 //<fun:it@9-2>
let f2 = f1 2.0 //4.0
然后按预期工作。但是,如果我要给函数a
和b
参数指定间隔,则intellisense会适合。
let ab = [0.0; 2.0]
let result =
let rec getres fn lst =
match lst with
| hd :: tl ->
let f1 = fn hd
getres f1 tl // <- error here
| [] -> fn
getres fx ab
然后f1
上的intellisense给我一个错误:
Type mismatch. Expecting a
"a -> 'b'
but given a
"b'.
The types "a' and "b -> 'a' cannot be unified
我希望能够将参数列表(例如,上例中的ab
列表)中的任意数量的参数递归地应用到我提供给表达式的函数中,形式为{{ 1}}。这可能吗?
答案 0 :(得分:3)
我认为您可能需要为getres
的函数参数指定一个签名。根据错误消息,编译器推断fn
接受单个参数并返回结果。因此在错误行f1
上不是函数而是值。就是没有任何烦人的事情发生。
但是,这将无法处理您想要执行功能而不是执行部分应用程序的最终情况。您可能需要额外的间接级别来处理此问题。 (在其他.NET语言中,可能需要为此使用反射-允许调用一个函数来传递参数数组-在强类型.NET语言中,如果没有反射就无法处理它。)
其他(总结以下评论):
请考虑所需的getres
签名。如果fn
是两个参数的函数(即'a -> 'a -> 'b
),则getres
具有签名:
('a -> 'a -> 'b) -> list 'a -> ('a -> 'b`)
第一次通话。
但是,当getres
的实例进行递归调用时,它需要是一个带有单个参数的函数,即。它的签名必须是:
('a -> 'b) -> list 'a -> 'b`
使用单个F#函数是不可能的。
.NET函数(即类成员)是可能的,但前提是必须分别编写每个“级别”(即,硬编码最大数量的参数)。 (比较.NET运行时中System.Func<T1, TRes>
,System.Func<T1, T2, TRes>
的定义。)
(这是动态语言可以轻松处理的事情,但是强类型语言需要在其基础上使用非常复杂的类型系统来实现。)