我有以下相当简单的 F# 函数:
let FormatValue (formatProvider : IFormatProvider) valueSuffix value =
match value > Convert.ToDecimal(valueSuffix.MinimumValueRequired) with
| true -> let normalizedValue = Convert.ToDecimal(value) / Convert.ToDecimal((Math.Pow(10., Convert.ToDouble(valueSuffix.PowerOfTen)))) in
string.Format("{0}{1}", normalizedValue.ToString(valueSuffix.Format, formatProvider), valueSuffix.Text)
| false -> ""
返回类型被正确推断为string
,但是我得到一个错误标记string.Format
in the true
分支,表示类型<'a> -> string
与类型不兼容ValueSuffix
。我发现这特别令人惊讶,因为所有其他类型都被正确推断,特别是没有其他发生<'a>
在函数中。
我在做什么和/或理解错误?
约翰·帕尔默的答案是正确的,但我经常想知道为什么string.Format
is not在 F# 代码中有效,直到这个问题我才懒得去调查它。
看着相关来源 https://github.com/fsharp/fsharp/blob/19507b98bc6a7995e9c19c40f044fdfeb578ef77/src/fsharp/FSharp.Core/prim-types-prelude.fs,我们看到string
只是一个类型别名System.String
。所以看来我们should能够像使用它一样System.String
。例如,假设我们定义以下类型别名:
type foo = System.String
这将使我们能够做类似的事情foo.Format
没有问题。
问题在于,不仅是string
定义为类型别名,它是还定义了 https://github.com/fsharp/fsharp/blob/19507b98bc6a7995e9c19c40f044fdfeb578ef77/src/fsharp/FSharp.Core/prim-types.fs#L4174作为转换函数。这有效地隐藏了类型别名,除非在仅需要类型名称的上下文中(例如类型注释和强制转换)。
我们可以通过定义我们自己的转换函数来演示这一点foo
类型别名:
let foo value =
match box value with
| null -> ""
| _ -> value.ToString()
现在前面提到的foo.Format
调用将无法编译。
所有其他基本类型也是如此(int
, float
, etc.).
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)