如何为函数组合选择正确的方法重载?

时间:2019-02-20 20:57:27

标签: f#

这是F#中函数的简单组合

let composedFunction = System.Text.Encoding.UTF8.GetBytes >> Array.length
"test" |> composedFunction

类型推断正确定义了组合函数string -> int的类型。但是编译器无法选择System.Text.Encoding.UTF8.GetBytes方法的正确重载:

  

错误FS0041:方法'GetBytes'的唯一重载不能   根据此程序点之前的类型信息确定。一种   可能需要类型注释。候选人:

     

System.Text.Encoding.GetBytes(chars:char []):字节[],

     

System.Text.Encoding.GetBytes(s:string):字节[] Blockquote

有什么办法可以组成更正System.Text.Encoding.UTF8.GetBytes的重载,该重载接受字符串参数?

或者当然,我可以照做

// declare function which calls correct overload and then use it for compostion
let getBytes (s: string) = System.Text.Encoding.UTF8.GetBytes s      
let composedFunction = getBytes >> Array.length

// start composition with ugly lambda
let composedFunction =
  (fun (s: string) -> s) >> System.Text.Encoding.UTF8.GetBytes >> Array.length

但是我想知道是否有没有其他函数声明的方法可以使编译器根据推断的string -> int类型的组合函数选择正确的重载?

2 个答案:

答案 0 :(得分:5)

您始终可以添加注释:

let composedFunction : string -> _ = System.Text.Encoding.UTF8.GetBytes >> Array.length

let composedFunction = (System.Text.Encoding.UTF8.GetBytes : string -> _) >> Array.length

答案 1 :(得分:1)

如您的示例所示,.NET方法并不总是能很好地构成-我认为在这种情况下,惯用的方法只是在处理.NET库时使用.NET样式(而当您处理.NET库时则使用函数样式)。关于功能库)。

在您的特定情况下,我将使用类型注释定义一个普通函数,并使用Length成员而不是使用该函数来获取长度:

let composedFunction (s:string) = 
  System.Text.Encoding.UTF8.GetBytes(s).Length

现有答案显示了如何使合成与类型注释一起使用。您可以做的另一种技巧(我在实践中肯定不会使用它们)是,您可以将string上的标识函数添加到组成中以约束类型:

let composedFunction = id<string> >> System.Text.Encoding.UTF8.GetBytes >> Array.length

这很有趣,但是正如我所说,我永远不会真正使用它,因为上面定义的普通函数更容易理解。