F# has various kinds of types. Standard .NET types (that also exist in C#) such as class, interfaces and delegates are mapped directly to the corresponding CLR representation.
You can also define value type using the Struct
attribute (in which case, you get a type corresponding to C# struct
) and an enumeration like this:
[<Struct>]
type ValueType(a:int) =
member x.A = a
type Enumeration =
| First = 1
| Second = 2
The remaining F# types are specific to F# and don't have any standard representation in CLR. F# compiler encodes them as a class (or several classes).
- Record is simply a class with properties corresponding to the fields of the record.
Tuple is represented using a generic Tuple<...>
class (which is new in .NET 4.0)
Function value is represented using a generic FSharpFunc<...>
type. This allows F# to implement currying & partial function application, so it is a bit tricky. For example, int -> int -> int
would be FSharpFunc<int, FSharpFunc<int, int>>
. The type has a single Invoke
method that you can use to call it with the first parameter. F# also generates a derived type that contains Invoke
method taking all the parameters, which is more efficient and is used most of the time.
Discriminated union is represented as a class hierarchy with an abstract base class (with the same name as the union type) and a subclass for each of the cases. For example:
type Shape =
| Rectangle of int * int * int * int
| Circle of int * int * int
This would create an abstract base class Shape
and two derived concrete classes Rectangle
and Circle
(actually, nested classes in the Shape
class). These derived classes would contain the fields needed to store the properties of the case (e.g. location of a rectangle).
If you want to know more, you can take a look at the Adventures in F# series by Jomo Fisher.