Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics ToString()与字符串运算符的类型推断_Generics_F#_Type Inference - Fatal编程技术网

Generics ToString()与字符串运算符的类型推断

Generics ToString()与字符串运算符的类型推断,generics,f#,type-inference,Generics,F#,Type Inference,注意:这个问题与我的有点相关,但实际上它从不同的角度触及了这个问题 考虑以下代码段: let toStr a = a.ToString() let strOp a = string a let intToStr = 5 |> toStr let floatToStr = 5.0 |> toStr let intStrOp = 5 |> strOp let floatStrOp = 5.0 |> strOp //type inference error 虽然strOp

注意:这个问题与我的有点相关,但实际上它从不同的角度触及了这个问题

考虑以下代码段:

let toStr a = a.ToString()
let strOp a = string a

let intToStr = 5 |> toStr
let floatToStr = 5.0 |> toStr

let intStrOp = 5 |> strOp
let floatStrOp = 5.0 |> strOp //type inference error
虽然
strOp
函数使用了看起来更优雅的解决方案,并且能够将单位值转换为字符串,但它似乎不是真正的泛型,因为它的类型在第一次使用时受到限制(即使推断的类型是
obj->string
,而不是
'a->string


为什么字符串运算符不能以这样一种通用的方式工作?或者我做错了什么?

区别在于
string
使用静态成员约束(请参阅),而
ToString
是任何对象上可用的普通方法,因此编译器将
ToString
调用视为通用代码,不以任何方式约束实例类型

静态约束和(非静态)泛型在(否则不受约束的)
let
-绑定函数中使用时以不同的方式工作:

  • 对于泛型代码,编译器传播泛型性,并使您编写的
    let
    绑定函数也具有泛型性

  • 对于静态成员约束,编译器根据第一次使用专门化代码。如注释中所述,您可以通过使用
    内联
    来避免这种情况,它允许基于静态成员的泛型以与顺序泛型代码相同的方式传播


我认为
string
函数使用静态解析的类型约束的唯一原因是它允许它专门化为对基本类型的普通
ToString
调用,但是仍然以自定义方式处理对象的
null
值-
tostrnull
抛出异常,但
strOp null
返回空字符串

让内联strOp a=string a
这是实现更高级多态性的著名技巧吗?如果我的问题是关于这一点,那么ToString示例为什么有效?我不明白其中的区别。因为
toStr
是一个真正的泛型函数,而
strOp
用静态解析的类型约束实例化了一个内联函数,但它本身不是内联的,因此不具有泛型性。这可能有助于解释细节:我不认为处理null是
string
具有静态约束的原因。如果您看一下,这些类型专门化看起来相当面向性能,即生成​ <代码>调用而不是已知基元类型的
callvirt
。空检查本身在via-boxing中执行得非常好,没有静态约束。