. Net – f#int.maxvalue is “not a valid constant expression”, but system Int32. What is maxvalue?
TL; Dr: the f# compiler interprets int as int operator in this context, such as determined by Eugene fotin and expanded upon by gene belitski The best solution is to use system int32. Maxvalue or unique type alias, as described below
Consider the following record types:
type User = { Username : string }
I want the user name to be at least three characters long, so I use the stringlength property There is no maximum length, so I set it to int.maxvalue:
type User = { [<StringLength(int.MaxValue,MinimumLength=3)>] Username : string }
This gave me the following errors:
Everything is peach, if I use system Int32 replaces:
type User = { [<StringLength(system.int32.MaxValue,MinimumLength=3)>] Username : string }
It also compiles if I alias int:
type User = { [<StringLength(num.MaxValue,MinimumLength=3)>] Username : string } and num = int
Or fully qualified type:
type User = { [<StringLength(Microsoft.FSharp.Core.int.MaxValue,MinimumLength=3)>] Username : string }
I checked the f# source and int is defined exactly as you would expect:
type int32 = system.int32 // Then,a few lines later… type int = int32
What's going on? I assume that f# primitive types are interchangeable with other types in most cases, but it looks like something missing from my mental model
Solution
This is how f# type inference works in different contexts, where different syntactic entities coincidentally have the same name, if int can be any of the following:
>Function int:'t > the full name of int is Microsoft FSharp. Core. Operators. Int > type the full name of int = int32 Microsoft FSharp. Core. Int > type int & "measure > = full name is Microsoft FSharp. Core. int< _>
One way to demonstrate this work would be if we just entered
int;;
In FSI, we will get something similar
val it : (int -> int) = <fun:it@3>
In other words, it is a function that cannot be associated with its maxvalue property:
> int.MaxValue;; int.MaxValue;; ----^^^^^^^^ ... error FS0039: The field,constructor or member 'MaxValue' is not defined
The same applies to int32. When used in the context of an expression, it is inferred by FSI as another function with only signature (int – > int32)
Now let's talk about
type num = int
In this context, int is inferred as system Int32's type name abbreviation, so num is also a type abbreviation, but now there is no ambiguity in the name, so num.maxvalue is what we expect, and what we expect is in FSI
> num.MaxValue;; val it : int = 2147483647
Finally, when you use Microsoft FSharp. Core. Int, you explicitly reference the type entity without any ambiguity, so it works as expected
Return to your use case attribute parameters - in this context, int is type inferred as part of an expression to provide parameter values, that is, as functions, unless you explicitly or indirectly set another interpretation