Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 30

Chapter 2

Datatypes and Bookkeeping

General discussion
Constructs
Records Members Generic records Units of measure

Records (*)
Complex data structure
Position x, position y, mass, etc Type
float*float*float*...*float

For the compiler are equivalent


(vx,vy,x,y,... ) (x,y,vx,vy,...)

Records (*)
type RECORD_NAME = { Field1Name : Field1Type; Field2Name : Field2Type; ... FieldnName : FieldnType }

Equivalent to the tuple of type:


Field1Type * Field2Type * ... * FieldnType

Records (*)
Example record
type Person = { Name : string; Surname : string; Age : int }

Creating a value of record type


{ Field1Name = v1; Field2Name = v2; ... FieldnName = vn }

Creating a value of type Person


let john_doe = { Name = "John"; Surname = "Doe"; Age = 37 }

Records (*)
Reading the fields of a record
let name = john_doe.Name

Type inference
let fullname x = x.Name+","+x.Surname

x has type Person

Records (*)
Modifying a record
{ x with FieldiName = vi; ... FieldjName = vj }

NB: a modified copy of the original record is created!

Example
let jane_doe = { john_doe with Name = "Jane" }

Members (*)
Member functions
Invoked with dot operator Increased capabilities of manipulation Indentation is very important

member SELF-NAME.FUNCTION-NAME = BODY

Members (*)
Example
type Employee = { Person : Person Job : string } member self.ChangeJob new_job = { self with Job = new_job }

Members (*)
Properties
Parameterless members
type Department = { Boss : Person NumEmployees : int Name : string } member this.Description = "Department "+this.Name+" is managed by "+this.Boss.Name

Members (*)
Static members
type Job = { Department : string HoursPerWeek : int SalaryPerWeek : int } static member CreateDefaultJob() = { Department = "Accounting"; HoursPerWeek = 40; SalaryPerWeek = 400 }

Members (*)
Mutable fields
type Traveler = { Person : Person mutable Location : string CurrentActivity : Ref<string> } let john_traveler = { Person = john_doe; Location = "Cambodia"; CurrentActivity = ref "Fishing" } do john_traveler.Location <- "California" do john_traveler.CurrentActivity := "Surfing"

Generic records (**)


Records with generic type Fields with a certain name and shape but of any possible tipe
type RECORD-NAME<RECORD-TYPE-PARAMS> = ...

RECORD-TYPE-PARAMS =
'a,'b,'c ,

type parameters like

...

Generic records (**)


Example
type Pair<'a,'b> = { First : 'a; Second : 'b }

let my_pair : Pair<int,string> = { First = 10; Second = "hello" }

Generic records (**)


let my_pair' = { First = { First = 10; Second = 5.0 }; Second = { First = System.DateTime.Now; Second = "hello" } }

Generic records (**)


Records with generic functions Example: the AI of a hero (prince, paladino, etc)
let hero_ai (hero:'a) = let p:Princess = find_nearest_princess hero.Position let monster:Monster = find_guardian p do fight hero monster

Generic records (**)


Additional parameters
Generic functions
let hero_ai (get_position:'a->Vector2<m>) (hero:'a) = let p:Princess = find_nearest_princess (get_position hero) let monster:Monster = find_guardian p do fight hero monster

Generic records (**)


Many operations can be grouped in a single record
type Number<'a> = { Zero : 'a; One : 'a; Sum : 'a -> 'a -> 'a; Mul : 'a -> 'a -> 'a; Neg : 'a -> 'a }

let line let (+) = num.Sum let (*) = num.Mul q+m*x

Generic records (**) num q m x =

let float_num = { Zero = 0.0; One Mul = (*); Neg = let int_num = { Zero = 0; One = Mul = (*); Neg =

= 1.0; Sum = (+); ( ~- ) } 1; Sum = (+); ( ~- ) }

let float_line = line float_num let int_line = line int_num let line_3x2 = int_line 2 3 let line_4x2 = float_line 2.0 4.0

Generic records (**)


Generic record of operations for complex numbers
let complex_num num = let (+) = num.Sum let (*) = num.Mul let ( ~- ) = num.Neg { Zero = (num.Zero,num.Zero) One = (num.One,num.Zero) Sum = fun (a,b) (c,d) -> (a+c,b+d) Mul = fun (a,b) (c,d) -> (a*c+(-(b*d)),b*c+a*d) Neg = fun (a,b) -> (-a,-b) }

Generic records (**)


Powerful programming style
Type-classes in Haskell Type-traits in Scala

Units of Measure (*)


Annotations added to existing types to avoid mixing incompatible values!

Units of Measure (*)


[<Measure>] type m [<Measure>] type kg [<Measure>] type s

[<Measure>] type N = kg*m/s^2

Units of Measure (*)


Adding a unit of measure to a value
let g = 9.81<m/s^2> let m:int<m> = 3<m> let x = 3.0<m>

Error
x+g

Units of Measure (*)


Conversion operations
[<Measure>] type km let m_to_km (v:float<m>) = v*1000.0<km/m> let km_to_m (v:float<km>) = v/1000.0<km/m>

Units of Measure (*)


Annotating records or other custom types
type Vector2< [<Measure>] 'a > = { X : float<'a>; Y : float<'a> } let v1 = { X = 1.0<m>; Y = 1.0<m> } let v2 = { X = 1.0<m/s>; Y = 1.0<m/s> }

Units of Measure (*)


let v3 = { X = v1.X/v2.X; Y = v1.Y/v2.Y }

Ok
let v4 = { X = v1.X/v2.X; Y = v2.Y/v1.Y }

Compiler error

Units of Measure as Contracts (**)


Confidential channels
[<Measure>] type confidential

[<Measure>] type public_domain


[<Measure>] type secure [<Measure>] type unsecure

Units of Measure as Contracts (**)


type Channel< [<Measure>] 's > = { Stream : System.IO.Stream }

type Communication< [<Measure>] 'd > = { Message : string }


let send_confidential_message (c:Channel<secure>,m:Communication<confidential>) = let send_public_message (c:Channel<'a>,m:Communication<public_domain>) =

Units of Measure as Contracts (**)


Confidential messages
Only through secure channel

Public messages
Through any channel

You might also like