ToString() 与字符串运算符的类型推断
Type inference on ToString() vs string operator
注:这个问题和我的有点关系,但其实从不同的角度触及了问题
考虑以下代码段:
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
使用静态成员约束(参见 the definition),而 ToString
是可用于任何对象的普通方法,因此编译器将 ToString
调用作为不以任何方式限制实例类型的通用代码。
静态约束和(非静态)泛型在(否则不受约束)let
-绑定函数中使用时以不同的方式工作:
对于通用代码,编译器传播通用性并使您编写的 let
绑定函数也通用。
对于静态成员约束,编译器根据首次使用对代码进行特殊化处理。如评论中所述,您可以通过使用 inline
来避免这种情况,它允许基于静态成员的泛型以与序号泛型代码相同的方式传播。
我认为 string
函数使用静态解析类型约束的唯一原因是它允许它像普通 ToString
原始类型调用一样专门化,但仍然处理 null
对象的自定义方式的值 - toStr null
抛出异常但 strOp null
returns 一个空字符串!
注:这个问题和我的
考虑以下代码段:
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
使用静态成员约束(参见 the definition),而 ToString
是可用于任何对象的普通方法,因此编译器将 ToString
调用作为不以任何方式限制实例类型的通用代码。
静态约束和(非静态)泛型在(否则不受约束)let
-绑定函数中使用时以不同的方式工作:
对于通用代码,编译器传播通用性并使您编写的
let
绑定函数也通用。对于静态成员约束,编译器根据首次使用对代码进行特殊化处理。如评论中所述,您可以通过使用
inline
来避免这种情况,它允许基于静态成员的泛型以与序号泛型代码相同的方式传播。
我认为 string
函数使用静态解析类型约束的唯一原因是它允许它像普通 ToString
原始类型调用一样专门化,但仍然处理 null
对象的自定义方式的值 - toStr null
抛出异常但 strOp null
returns 一个空字符串!