F# programs are built around types. With types, we group related pieces of data together. We add behavior (in functions and properties) to our types.
When specifying a type, we can add initialization logic. This ensures each instance of the type is valid. We can specify members of a type.
Here we introduce an Animal type. To create an animal we must specify an int
for its size (this is like its constructor).
int
. It returns the size times 10.type Animal(s : int) = // Store the argument in the object. let mutable size = s // Write a helpful message. do printfn "Animal created, size = %A" size // For Weight, return size times 10, an int. member x.Weight : int = size * 10 // Create an Animal with size 5. let animal = Animal 5 // Get the Weight of the animal. let weight = animal.Weight printfn "%A" weightAnimal created, size = 5 50
Properties help us control how a type is used. Here we introduce a type Box that has a Color property. With the get()
and set()
keywords we add accessors.
get()
accessor. This returns the value of the "color" mutable field.type Box() =
// A mutable color field.
let mutable color : string = null
// A Box has a color property with get and set.
member x.Color
with get() = color
and set(c) = color <- c
// Create a Box instance.
let x = Box()
// Set and get color values.
x.Color <- "blue"
printfn "%A" x.Color
// Set another value.
x.Color <- "red"
printfn "%A" x.Color"blue"
"red"
This is an operator that returns the System.Type
instance for the specified type. We must place a type name within the angle brackets.
typeof
we get the System.Type
.// A type with one field.
type Color() =
let mutable Value = null
// Get typeof Color type.
// ... This is an instance of System.Type.
let t = typeof<Color>
printfn "%A" tProgram+Color
In F# we can use tuples and records to store data. But for important, often-used information, we use types. This gives us a way to add helpful methods and validation.