Data
Algebraic Data Types
Data Structures
// F#�type MyList = {value : int; ref : MyList};
Algebraic Data Types
// F#�type option_int = None | Some of int
A piece of data that is either nothing, or an integer.
Divided by zero? Return None. Else return integer
// F#�type int_list = Nil | Cons of int * int_list
A list of integers: either the empty list (Nil) or �an integer and the rest of the list
Case or Matching Statements
// F#�type option_int = None | Some of int
let f (x : option_int) =
match x with
| None -> printfn "Nope"
| Some v -> printfn "%i" v
in
f (Some 3); f(None)
Prints “3” and then “Nope”
Case or Matching Statements
// F#�type option_int = None | Some of int
let rec print_list l =
match l with
| Nil -> printfn "End"
| Cons(head, rest) ->
printfn "%i," head; � print_list rest
in� let l = Cons(1, Cons(2, Cons(3, Nil))) in
print_list l
Prints �“1,2,3,End”
Example
// F#�type t = L of int | N of int * t * t
Example
// F#�type t = L of int | N of int * t * t
// F#�type Tree = Leaf of int | Node of int * Tree * Tree
Example
�Also like Enums
// F#�type Color = Red | Green | Blue
Algebraic Data Types
Products
let x = (1, 2) in� print x.L ;
print x.R
(1, 2).L = 1
(1, 2).R = 1
Semantics
Types
Sums
let None = inl () in�let Some(x) = inr x in …
let f (x) =
case x {
| L(v) -> print "Nope"
| R(v) -> print "%i" v }
in
f (Some 3); f(None)
Sums
// F#�type option_int = None | Some of int
let f (x : option_int) =
match x with
| None -> printfn "Nope"
| Some v -> printfn "%i" v
in
f (Some 3); f(None)
Sums
// F#�type option_int = None | Some of int
let f (x : option_int) =
match x with
| None -> printfn "Nope"
| Some v -> printfn "%i" v
in
f (Some 3); f(None)
let None = inl () in�let Some(x) = inr x in …
let f (x) =
case x {
| L(v) -> print "Nope"
| R(v) -> print "%i" v }
in
f (Some 3); f(None)
Semantics
Types
More than Binary
// F#�type color = Red | Green | Blue
More than Binary
// F#�type color = Red | Green | Blue
let Red = inl () in�let Green = inr (inl ()) in
let Blue = inr (inr ()) in …
A little more…
let Red = inl () in�let Green = inr (inl ()) in
let Blue = inr (inr ()) in …
// F#�type color = Red | Green | Blue
// F#�type position = Left | Center | Right
let Left = inl () in�let Center = inr (inl ()) in
let Right = inr (inr ()) in …
A little more…
let Red = inl () in�let Green = inr (inl ()) in
let Blue = inr (inr ()) in …
// F#�type color = Red | Green | Blue
// F#�type position = Left | Center | Right
let Left = inl () in�let Center = inr (inl ()) in
let Right = inr (inr ()) in …
Structural typing mean these are interchangeable
Variants (unique labels)
let Red = <color.Red = ()> in�let Green = <color.Green = ()> in
let Blue = < color.Blue – ()> in
// F#�type color = Red | Green | Blue
// F#�type position = Left | Center | Right
let Left = <position.Left = ()> in�let Center = <position.Center = ()> in
let Right = <position.Right = ()> in
Some Final Details
let Red = <color.Red = ()> in�let Green = <color.Green = ()> in
let Blue = < color.Blue – ()> in
let f (x) =
case x {
| <color.Red = v> -> print ”Red”
| <color.Green = v> -> print ”Green”
| <color.Blue = v> -> print ”Blue”�in
f (Some 3); f(None)
// F#�type color = Red | Green | Blue
Handle tagging in case statement
Some Final Details
let Red = <color.Red = ()> in�let Green = <color.Green = ()> in
let Blue = < color.Blue – ()> in
let f (x) =
case x {
| <color.Red = v> -> print ”Red”
| <color.Green = v> -> print ”Green”
| <color.Blue = v> -> print ”Blue”�in
f (Some 3); f(None)
// F#�type color = Red | Green | Blue
Also can perform exhaustiveness
checking
Recursive Types
// F#�type int_list = Nil | Cons of int * int_list
Why Algebraic?
Why Algebraic?
Conclusion