TL; DR: F#编译器解释int
在这种情况下为int
操作者,如由Eugene Fotin确定和通过基因Belitski时膨胀.最佳解决方法是使用System.Int32.MaxValue
或如下所述的唯一类型别名.
请考虑以下记录类型:
type User = {
Username : string
}
我想要Username
至少三个字符,所以我使用该StringLength
属性.没有最大长度,所以我将它设置为int.MaxValue
:
type User = {
[]
Username : string
}
这给了我以下错误:
这不是有效的常量表达式或自定义属性值.
如果我使用的话,一切都是桃子的System.Int32
:
type User = {
[]
Username : string
}
如果我别名它也会编译int
:
type User = {
[]
Username : string
}
and num = int
或完全符合类型:
type User = {
[]
Username : string
}
我检查了F#源代码,并且int
完全按照您的预期定义:
type int32 = System.Int32
// Then, a few lines later…
type int = int32
这是怎么回事?我假设F#原始类型在大多数情况下都可与其他类型互换,但看起来我的心理模型中缺少某些东西.
看起来编译器将int
属性的参数视为转换函数int
.
这就是F#类型推断如何在不同的语境中工作,其中不同的语法实体巧合地具有相同的名称,在以下情况中int
可以是以下任何一种:
int:'T->int
全名功能Microsoft.FSharp.Core.Operators.int
type int = int32
全名 Microsoft.FSharp.Core.int
type int<'Measure> = int
全名 Microsoft.FSharp.Core.int<_>
演示此工作的一种方法是以下场景:如果我们只是输入
int;;
在FSI,我们会得到类似的东西
val it : (int -> int) = <fun:it@3>
换句话说,它是一个不能具有MaxValue
与之关联的属性的函数:
> int.MaxValue;; int.MaxValue;; ----^^^^^^^^ ... error FS0039: The field, constructor or member 'MaxValue' is not defined
同样适用于int32
,当在表达的上下文中使用时,由FSI推断为具有签名的另一个函数(int -> int32)
.
现在说到了
type num = int
在这个上下文中int
被推断为类型名称的缩写System.Int32
,因此num
也是类型缩写,但现在名称歧义没有位置,因此num.MaxValue
推断出我们期望它的确切含义,在FSI中给出
> num.MaxValue;; val it : int = 2147483647
最后,当您使用Microsoft.FSharp.Core.int
显式引用类型实体时,没有模糊性的地方,因此它按预期工作.
回到带有属性参数的用例 - 在此上下文int
中,类型推断将其作为表达式的一部分来处理,以传递参数值,即作为函数,除非您明确或间接设置另一个解释.