在ToString()与字符串运算符上输入推论 [英] Type inference on ToString() vs string operator

查看:128
本文介绍了在ToString()与字符串运算符上输入推论的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:这个问题与我的前一个,但实际上从不同的角度触及问题



请考虑下面的代码片段:

<$ p $ > 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 //类型推断错误

虽然 strOp 函数使用看起来更优雅的解决方案,并且能够将单位值转换为字符串,它似乎不是真正的通用类型,因为它的类型在第一次使用期间受到限制(即使推断的类型是 obj - > string ,而不是'a - >字符串

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

解决方案

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

静态约束和(非静态)泛型以不同方式使用(否则不受限制) let -bound函数:


  • 对于泛型代码,编译器会传播泛型并使 let - 你也写了泛型函数。

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




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


Note: This question is somewhat related to my previous one, but it actually touches the issue from different perspective

Consider following snippet:

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

While the strOp function uses what appears to be more elegant solution, and is able to convert a unit value to string as well, it seems not to be truly generic since it's type gets constrained during it's first usage (even the type inferred is obj -> string, not 'a -> string)

Why doesn't string operator work in such a generic way? Or am I doing something wrong?

解决方案

The difference is that string uses static member constraints (see the definition) while ToString is an ordinary method available on any object and so the compiler treats the ToString invocation as generic code that does not constrain the instance type in any way.

Static constraints and (non-static) generics work in different ways when they are used in (otherwise unconstrained) let-bound function:

  • For generic code, the compiler propagates the genericity and makes the let-bound function you wrote generic too.

  • For static member constraints, the compiler specializes the code based on the first use. As mentioned in the comments, you can avoid this by using inline, which allows static member-based genericity to propagate in the same way as ordinal generic code.

I think the only reason why the string function uses statically resolved type constraints is that it allows it to specialize as ordinary ToString call for primitive types, but still handle null values in custom way for objects - toStr null throws an exception but strOp null returns an empty string!

这篇关于在ToString()与字符串运算符上输入推论的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆