【问题标题】:Converting an F# Function with multiple parameters to a Func Type - MathNet.Numerics将具有多个参数的 F# 函数转换为 Func 类型 - MathNet.Numerics
【发布时间】:2018-01-15 18:00:57
【问题描述】:

在这个问题中:In F# how can I produce an expression with a type of Func<obj>? 表明单值 lambda 表达式会自动转换/转换为 Func 类型,然后在函数中接受。

我正在使用 MathNet.Numerics 库,可以通过在 0 到 10 之间积分 x^2 来确认这一点:

#r "../packages/MathNet.Numerics.3.20.0/lib/net40/MathNet.Numerics.dll"
#r "../packages/MathNet.Numerics.FSharp.3.20.0/lib/net40/MathNet.Numerics.FSharp.dll"

#load "Library1.fs"
open Library3

// Define your library scripting code here

open MathNet.Numerics.Integration

let integral = DoubleExponentialTransformation.Integrate((fun x -> x**2.0), 0.0, 10.0, 1.0)

val answer : float = 333.3333333

但是,我不能让它与多值函数一起使用。当我尝试这个时,我得到一个类型错误。有谁知道解决这个问题的方法?

open MathNet.Numerics.Optimization
open MathNet.Numerics.LinearAlgebra.Double

let newAnswer = BfgsSolver.Solve(DenseVector[|1.0, 1.0|], 
                                 (fun x y -> (x + y - 5.0) ** 2.0 + (y - x*x - 4.0) ** 2.0), 
                                 (fun x y -> DenseVector[| 2.0 * (x + y - 5.0) - 4.0 * x * (y - x*x - 4); 
                                                           2.0 * (x + y - 5.0) + 2.0 * (y - x*x - 4.0)   |])
                                                           )

我收到以下错误...

Script.fsx(20,34): error FS0193: Type constraint mismatch. The type 
    ''a -> 'b -> 'c'    
is not compatible with type
    'System.Func<MathNet.Numerics.LinearAlgebra.Vector<float>,float>'   

【问题讨论】:

  • 尝试fun (x, y) -&gt; 而不是fun x y -&gt; 不在电脑上,稍后将转换为答案。
  • @CaringDev 我有点沮丧地发现这不起作用,至少在我使用IEnumerable.Aggregate的测试中
  • @TheQuickBrownFox 很有可能...没有做太多 F# -> C# 交互,不记得我最后遇到的确切情况。

标签: c# f# mathematical-optimization func mathnet-numerics


【解决方案1】:

你可以使用System.Func&lt;_,_,_&gt;()来转换这样的函数:

let newAnswer = BfgsSolver.Solve(DenseVector[|1.0, 1.0|], 
                                 (System.Func<_,_,_>(fun x y -> (x + y - 5.0) ** 2.0 + (y - x*x - 4.0) ** 2.0)),
                                 (System.Func<_,_,_>(fun x y ->
                                    DenseVector[| 2.0 * (x + y - 5.0) - 4.0 * x * (y - x*x - 4)
                                                  2.0 * (x + y - 5.0) + 2.0 * (y - x*x - 4.0) |])))

如果你发现自己经常需要这个,你可以使用帮助器让代码变得不那么难看:

let f2 f = System.Func<_,_,_> f

更新

看看Math.NET documentation for this method,我现在看到它实际上只需要一个输入即可。也许您对Func&lt;A, B&gt; 类型签名感到困惑,但在这种情况下,A 是输入类型,B 是输出类型。

具有一个输入的 F# 函数会自动转换为 Func&lt;_,_&gt;。我下载了 Math.NET,这个非常小的示例没有给出编译错误:

open MathNet.Numerics.Optimization
open MathNet.Numerics.LinearAlgebra.Double
BfgsSolver.Solve(DenseVector [||], (fun x -> x.[0]), (fun x -> x))

这表明问题不在于函数类型之间的转换,而在于使用具有错误数量的函数。我应该从您的原始错误消息中看到这一点!

【讨论】:

  • 感谢您对 QBF 的回复。我仍然有类型问题,所以我尽可能地转换了所有内容: let f2 f = System.Func<_> f let newAnswer = BfgsSolver.Solve(a, b, (f2 (fun (x : MathNet. Numerics.LinearAlgebra.Vector) -> [| 2.0 * (x.[0] + x.[1] - 5.0) - 4.0 * x.[0] * (x.[1] - x.[0 ]*x.[0] - 4); 2.0 * (x.[0] + x.[1] - 5.0) + 2.0 * (x.[1] - x.[0]*x.[0] - 4.0) |]) : MathNet.Numerics.LinearAlgebra.Vector) )但它仍然给我的错误。您是否检查过您的解决方案是否有效?当我粘贴到 Visual Studio 时出现错误
  • 好的,但我最初的问题是如何使用多个参数,在您的回答中,您实际上是在使用单个参数 _,我们已经在原始示例中使用 Integrate 函数验证了该参数。在我上面的回复中,我尝试将变量转换为向量(因为我的实际问题涉及多个参数),但这给出了其他错误......您有任何替代建议吗?
  • @Shillington 您还没有展示实际需要提供具有两个输入的 Func 的示例,因此我无法判断您的问题可能出在哪里。我认为我的原始答案应该处理它。请注意,您评论中的f2 与我的回答中的f2 不同。
  • @Fox 原来的帖子有这个功能:fun xy -> (x + y - 5.0) ** 2.0 + (y - x*x - 4.0) ** 2.0),不是表示这个的函数需要两个参数吗?
  • @Shillington 是的,但是该方法不接受带有两个参数的函数,这就是您出现编译错误的原因。
猜你喜欢
  • 2021-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-17
相关资源
最近更新 更多