Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

string vs String - single case discriminated union

Tags:

string

.net

f#

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
like image 360
NoIdeaHowToFixThis Avatar asked Mar 17 '14 15:03

NoIdeaHowToFixThis


People also ask

When to use discriminated union?

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.

How is a discriminated union defined?

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.

Does C# have union types?

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.

What is a union in F#?

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.


1 Answers

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"
like image 140
Tomas Petricek Avatar answered Oct 30 '22 10:10

Tomas Petricek