The existing answer is correct in that string is a type of F #, and string not a type (unless you open the System namespace), so the two definitions are different. The first case creates a type alias, while the second declares a discriminatory union (and not the module alias, as suggested in the existing answer).
In the first case, the definition creates only the type alias. We can verify this using typeof<T> :
> type MyString = string;; > typeof<MyString>.FullName;; val it : string = "System.String"
In the second case, you define a discriminated union in which there is one case with the name string (the name could be anything - the main thing is that string not a known type, and therefore it is treated simply as the name of the case). To verify 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 = ()
A definition is simply a very simple case of discriminated union. We could add more cases, and cases may also contain fields:
type MyString = String | SomeOtherName of int
The trick is that string not a known type name. If you open the System namespace, you again get just an alias like:
> open System;; > type MyString = String;; > typeof<MyString>.FullName;; val it : string = "System.String"
source share