在重构一些F#代码时,我遇到了一个我无法理解或解决的问题。我有一个类问题,有2个构造函数,一个默认用于F#消费,一个用于C#方便,它接受Func并将它们“转换”为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#友好构造函数中的mutator 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个函数似乎具有正确的签名,但最后一行失败并显示红色波浪形,告诉我“无法根据此程序之前的类型信息确定方法'问题`2'的唯一重载点。可用的重载如下所示(或在错误列表窗口中)。可能需要类型注释。“
任何人都可以帮我看看我错过了什么吗?我试着在最后一行输入4个参数的注释,但没有用 - 我不知道如何解决这个问题。令我感到奇怪的是,之前的版本很有用,只需在Func中反转2个参数。
答案 0 :(得分:2)
阅读规范(8.13.6)给出:
第一个类型导向转换将匿名函数表达式和其他函数值参数转换为委托类型。 给出:
委托类型D的形式参数
·已知类型
的实际参数fargty1 -> ... -> tyn -> rty
·确切地说是委托类型D的Invoke方法的参数
然后:
·该参数被解释为它被写成:
new D(fun arg1 ... argn -> farg arg1 ... argn)
由于这些条件适用,Func
代表将转换为咖喱形式,因此存在歧义。