type IntAndBool = {intPart: int; boolPart: bool } // This is a `product` type. i.e. It is made from other simple types let x = {intPart=1; boolPart=false} // This is data of type `IntAndBool` type IntOrBool = | IntChoice of int | BoolChoice of bool // This is a `sum` type, i.e. it is made up of either simple type specified here let y = IntChoice 42 let z = BoolChoice true // We can use types to achieve similar control flows to that of imperative languages. // Here is code that is analagous to an if-then-else construct let booleanExpression = true match booleanExpression with | true -> printfn "true" // Do things for true | false -> printfn "false" // Do things for false // Notice that this is very concise syntax and gets to the core of what we want to do // Here's a 'switch' statement let aDigit = 3 match aDigit with | 1 -> printfn "1" // Do things for 1 | 2 -> printfn "2" // Do things for 2 | _ -> printfn "Something else" // like 'default' in switch // For loops are replaced with recursion let aList = [1;2;3] let rec printList list = match list with | [] -> [] // Empty | head::tail -> // Process first element, then recurse printfn "%d" head printList tail printList aList // To do something like polymorphism // we create `sum types` type Shape = | Circle of radius:int | Rectangle of height:int * width:int // Note tuples defined with '*' | Point of x:int * y:int | Polygon of pointList:(int * int) list let draw shape = match shape with | Circle radius -> printfn "The circle has radius: %d" radius | Rectangle (height, width) -> printfn "Height is %d" height // etc.. | Polygon points -> points |> List.iter (printfn "%A") // you get it | _ -> printfn "I'm done" // Then you can do things with lists like: // shapes |> List.iter draw (imagine shapes is a list of shapes)