(* Programming language concepts for software developers, 2009-08-19 * *)
(* The meta language F#, a crash course *)
(* File appendix.fs *)
(* Arithmetic expressions, the int type *)
3+4;;
(* Variables and binding *)
let res = 3+4;;
res * 2;;
(* Arithmetic expressions, the float type *)
let y = sqrt 2.0;;
(* Using methods from the .NET class library *)
open System;;
let y = Math.Sqrt 2.0;;
(* Logical expressions, the bool type *)
let large = 10 < res;;
(* Conditional expressions, logical operators, conditional expressions *)
y > 0.0 && 1.0/y > 7.0;;
not false ;;
if 3 < 4 then 117 else 118;;
(* String-valued expressions *)
let title = "Professor";;
let name = "Lauesen";;
let junkmail = "Dear " ^ title ^ " " ^ name ^ ", You have won $$$!";;
junkmail.Length;;
(* Function declarations *)
let circleArea r = System.Math.PI * r * r;;
let a = circleArea 10.0;;
let mul2 x = 2.0 * x;;
mul2 3.5;;
let junkmail title name =
"Dear " ^ title ^ " " ^ name ^ ", You have won $$$!";;
junkmail "Vice Chancellor" "Tofte";;
(* Recursive function declarations *)
let rec fac n = if n=0 then 1 else n * fac(n-1);;
fac 7;;
(* Mutually recursive function declarations *)
let rec even n = if n=0 then true else odd (n-1)
and odd n = if n=0 then false else even (n-1);;
(* Type constraints *)
let isLarge (x : float) : bool = 10.0 < x;;
isLarge 89.0;;
(* Local scope using let-in bindings *)
let x = 5;; (* old x is 5 : int *)
let x = 3 < 4 (* new x is true : bool *)
in if x then 117 else 118;; (* using new x *)
x;; (* old x is still 5 *)
(* Pattern matching *)
let rec fac n =
match n with
| 0 -> 1
| _ -> n * fac(n-1);;
(* Anonymous function defined by pattern matching *)
let rec fac =
function
| 0 -> 1
| n -> n * fac(n-1);;
(* Pairs and tuples, product types *)
let p = (2, 3);;
let w = (2, true, 3.4, "blah");;
let add (x, y) = x + y;;
add (2, 3);;
let noon = (12, 0);;
let talk = (15, 15);;
let earlier ((h1, m1), (h2, m2)) = h1
0
| x::xr -> x + sum xr;;
let x2sum = sum x2;;
let rec prod xs =
match xs with
| [] -> 1
| x::xr -> x * prod xr;;
let x2prod = prod x2;;
let rec len xs =
match xs with
| [] -> 0
| x::xr -> 1 + len xr;;
let x2len = len x2;;
let sslen = len ss;;
let x3 = [47; 11];;
let x1x3 = x1 @ x3;;
(* Record types, record values, and labels *)
type phonerec = { name : string; phone : int };;
let x = { name = "Kasper"; phone = 5170 };;
x.name;;
x.phone;;
(* Exceptions *)
exception IllegalHour;;
let mins h =
if h < 0 || h > 23 then raise IllegalHour
else h * 60;;
mins 25;;
try (mins 25) with IllegalHour -> -1;;
let mins h =
if h < 0 || h > 23 then failwith "Illegal hour"
else h * 60;;
mins 25;;
let mins h =
if h < 0 || h > 23 then failwithf "Illegal hour, h=%d" h
else h * 60;;
mins 25;;
(* Algebraic datatypes *)
type person =
| Student of string (* name *)
| Teacher of string * int;; (* name and phone no *)
let people = [Student "Niels"; Teacher("Peter", 5083)];;
let getphone person =
match person with
| Teacher(name, phone) -> phone
| Student name -> raise (Failure "no phone");;
getphone (Student "Niels");;
(* The option datatype *)
type intopt =
| Some of int
| None;;
let getphone person =
match person with
| Teacher(name, phone) -> Some phone
| Student name -> None;;
getphone (Student "Niels");;
(* Representing binary trees using a recursive datatype *)
type inttree =
| Lf
| Br of int * inttree * inttree;;
let t1 = Br(34, Br(23, Lf, Lf), Br(54, Lf, Br(78, Lf, Lf)));;
let rec sumtree t =
match t with
| Lf -> 0
| Br(v, t1, t2) -> v + sumtree t1 + sumtree t2;;
let t1sum = sumtree t1;;
(* Curried functions: int -> int -> int versus int * int -> int *)
let addp (x, y) = x + y;;
let addc x y = x + y;;
let res1 = addp(17, 25);;
let res2 = addc 17 25;;
let addSeventeen = addc 17;;
let res3 = addSeventeen 25;;
let res4 = addSeventeen 100;;
(* Polymorphic functions *)
let rec len xs =
match xs with
| [] -> 0
| x::xr -> 1 + len xr;;
len [7; 9; 13];;
len ["Oslo"; "Aarhus"; "Gothenburg"; "Copenhagen"];;
(* Polymorphic datatypes *)
type 'a tree =
| Lf
| Br of 'a * 'a tree * 'a tree;;
let t1 = Br(34, Br(23, Lf, Lf), Br(54, Lf, Br(78, Lf, Lf)));;
let rec sumtree t =
match t with
| Lf -> 0
| Br(v, t1, t2) -> v + sumtree t1 + sumtree t2;;
let rec count t =
match t with
| Lf -> 0
| Br(v, t1, t2) -> 1 + count t1 + count t2;;
let rec preorder1 t =
match t with
| Lf -> []
| Br(v, t1, t2) -> v :: preorder1 t1 @ preorder1 t2;;
preorder1 t1;;
(* Accumulating parameters, for efficiency *)
let rec preo t acc =
match t with
| Lf -> acc
| Br(v, t1, t2) -> v :: preo t1 (preo t2 acc);;
let preorder2 t = preo t [];;
(* Type abbreviations *)
type intenv = (string * int) list;;
let bind1 (env : intenv) (x : string, v : int) : intenv = (x, v) :: env;;
bind1 [("age", 47)] ("phone", 5083);;
(* Higher-order functions *)
let rec map f xs =
match xs with
| [] -> []
| x::xr -> f x :: map f xr;;
let mul2 x = 2.0 * x;;
map mul2 [4.0; 5.0; 89.0];;
map isLarge [4.0; 5.0; 89.0];;
(* Anonymous functions *)
fun x -> 2.0 * x;;
map (fun x -> 2.0 * x) [4.0; 5.0; 89.0];;
map (fun x -> 10.0 < x) [4.0; 5.0; 89.0];;
let tw g x = g (g x);;
let quad = tw mul2;;
quad 7.0;;
fun x y -> x+y;;
fun x -> fun y -> x+y;;
let increaseBoth = fun i (x, y) -> (x+i, y+i);;
let isZeroFirst = function | [0] -> true | _ -> false;;
(* Higher-order functions on lists *)
let rec filter p xs =
match xs with
| [] -> []
| x::xr -> if p x then x :: filter p xr else filter p xr;;
let onlyEven = filter (fun i -> i%2 = 0) [4; 6; 5; 2; 54; 89];;
let rec foldr f xs e =
match xs with
| [] -> e
| x::xr -> f x (foldr f xr e);;
let len xs = foldr (fun _ res -> 1+res) xs 0;;
let sum xs = foldr (fun x res -> x+res) xs 0;;
let prod xs = foldr (fun x res -> x*res) xs 1;;
let map g xs = foldr (fun x res -> g x :: res) xs [];;
let listconcat xss = foldr (fun xs res -> xs @ res) xss [];;
let stringconcat xss = foldr (fun xs res -> xs ^ res) xss "";;
let filter p xs = foldr (fun x r -> if p x then r else x :: r) xs [];;
(* References and updatable state *)
let r = ref 177;;
let v = !r;;
r := 288;;
!r;;
let nextlab = ref -1;;
let newLabel () = (nextlab := 1 + !nextlab; "L" ^ string (!nextlab));;
newLabel();;
newLabel();;
newLabel();;
(* Arrays *)
let arr = [| 2; 5; 7 |];;
arr.[1];;
arr.[1] <- 11;;
arr;;
arr.Length;;