If string
is an alias of String in the .net framework why does this happen and how should I interpret it:
type JustAString = string
> type JustAString = string
type JustAStringAgain = String
> type JustAStringAgain = | String
Discriminated unions are useful for heterogeneous data; data that can have special cases, including valid and error cases; data that varies in type from one instance to another; and as an alternative for small object hierarchies.
A discriminated union is a union data structure that holds various objects, with one of the objects identified directly by a discriminant. The discriminant is the first item to be serialized or deserialized. A discriminated union includes both a discriminant and a component.
Union types are common in functional languages, but have yet to make it to C# and similar. These types solve a simple and very common problem, data that is one of a finite set of possibilities.
In F#, a sum type is called a “discriminated union” type. Each component type (called a union case) must be tagged with a label (called a case identifier or tag) so that they can be told apart (“discriminated”). The labels can be any identifier you like, but must start with an uppercase letter.
The existing answer is correct in that string
is an F# type while String
is not a type (unless you open the System
namespace), which is why the two definitions differ. The first case creates a type alias, while the second one declares a discriminated union (rather than a module alias as suggested in the existing answer).
In the first case, the definition creates just a type alias. We can check this using typeof<T>
:
> type MyString = string;;
> typeof<MyString>.FullName;;
val it : string = "System.String"
In the second case, you are defining a discriminated union that has a single case named String
(the name could have been anything - the key thing is that String
is not a known type and so it is treated just as a name of the case). To check this, we can use GetUnionCases
from the F# reflection module:
> type MyString = String;;
type MyString = | String
> open Microsoft.FSharp.Reflection
for u in FSharpType.GetUnionCases(typeof<MyString>) do
printfn "%s" u.Name;;
String
val it : unit = ()
The definition is simply a very basic case of discriminated union. We could add more cases and the cases could contain fields too:
type MyString = String | SomeOtherName of int
The trick is that String
is not a known type name. If you open the System
namespace, then you get just a type alias again:
> open System;;
> type MyString = String;;
> typeof<MyString>.FullName;;
val it : string = "System.String"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With