更改 Func 参数顺序后,F# 构造函数无法构建

标签 f# constructor overloading

在重构一些 F# 代码时,我遇到了一个我无法理解或解决的问题。我有一个类问题,有 2 个构造函数,一个默认用于 F# 消耗,一个用于 C# 方便,它接受 Funcs 并将它们“转换”为 F# 函数:

open System

type Problem<'d, 's> (data: 'd, generate: 'd -> Random -> 's, mutate: 'd -> Random -> 's -> 's, evaluate: 's -> float) =

   member this.Data = data
   member this.Generate = generate this.Data
   member this.Mutate = mutate this.Data
   member this.Evaluate = evaluate   

   new (data: 'd, generator: Func<'d, Random, 's> , mutator: Func<'d, 's, Random, 's> , evaluator: Func<'s, float>) =
      let generate (data: 'd) rng = generator.Invoke(data, rng)
      let mutate  (data: 'd) (rng: Random) (solution: 's) = mutator.Invoke(data, solution, rng)
      let evaluate (solution: 's) = evaluator.Invoke(solution)
      Problem(data, generate, mutate, evaluate)

据我所知,它的构建和工作符合预期。

出于某种强制性,我注意到 C# 友好的构造函数中的变元 Func 对于参数有不同的顺序,因此我继续以这种方式重写它(第一部分不变):

   new (data: 'd, generator: Func<'d, Random, 's> , mutator: Func<'d, Random, 's, 's> , evaluator: Func<'s, float>) =
      let generate = fun (data: 'd) rng -> generator.Invoke(data, rng)
      let mutate = fun (data: 'd) (rng: Random) (solution: 's) -> mutator.Invoke(data, rng, solution)
      let evaluate = fun (solution: 's) -> evaluator.Invoke(solution)
      Problem(data, generate, mutate, evaluate)

虽然这 3 个函数似乎具有正确的签名,但最后一行失败并显示红色波浪线,告诉我“无法根据此程序之前的类型信息确定方法‘Problem`2’的唯一重载点。可用的重载如下所示(或在“错误列表”窗口中)。可能需要类型注释。

谁能帮我看看我错过了什么?我尝试对最后一行中的 4 个参数进行类型注释,但无济于事 - 而且我不知道如何解决这个问题。同样让我感到奇怪的是,以前的版本只需在 Func 中反转 2 个参数就可以工作。

最佳答案

阅读规范(8.13.6)给出:

The first type-directed conversion converts anonymous function expressions and other function-valued arguments to delegate types. Given:

A formal parameter of delegate type D

· An actual argument farg of known type ty1 -> ... -> tyn -> rty

· Precisely n arguments to the Invoke method of delegate type D

Then:

· The parameter is interpreted as if it were written: new D(fun arg1 ... argn -> farg arg1 ... argn)

当这些条件适用时,Func 委托(delegate)将转换为柯里化(Currying)形式,因此存在歧义。

关于更改 Func 参数顺序后,F# 构造函数无法构建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10792054/

相关文章:

.net - 相同的属性,不同的类型

F# 叉管

visual-studio-2012 - 在 Visual Studio 2012 中使用 F# 的内联函数的代码覆盖率

macos - 如何为 F# 项目/脚本的运行/调试设置 Visual Studio Code?

reactjs - 如何使用 React Hooks 将带有构造函数的类转换为功能组件?

java - java中通过构造函数实例化对象失败

c++ - 如何为一组对象重载运算符

inheritance - 继承类型时获取 "value is not defined"

c# - 使用通过私有(private)构造函数返回新实例的静态方法有优势吗?

c# - 使用类层次结构重载 - 大多数派生未使用