let i1 = 12 let i2 = 23 + 23 let i3 = 0x80d099FE
let a1 = 0x00FE &&& 0x1211 // and let a2 = 0x00FE ||| 0x1211 // or let a3 = 0x00FE ^^^ 0x1211 // xor let a4 = ~~~ a3 // not let a5 = 0x1234 <<< 3 // left shift let a6 = 0x1234 >>> 2 // right shift do printf "%08x %08x %08x\n" a1 a2 a3 do printf "%08x %08x %08x\n" a4 a5 a6
Compatibility note:
let r1 = 2.0 * 3.1415 + 1.0 let r2 = float 123 do printf "%f %f\n" r1 r2 let r1_caml = 2.0 *. 3.1415 +. 1.0
let strA = "SySt3M H4Ck4Rz" let strB = "Network Police" // MLLib.String functions: let lenA = String.length strA // length let strC = strA ^ " out fox " ^ strB // concatenation let strD = String.sub strA 7 7 // substring // System.String static/instance methods let lenD = strD.Length // property let strE = strD.ToUpper() // instance method
Find documentation online by searching for:
let tupA = 1,false let tupB = 1,true,"three" let fst (a,b) = a let snd (a,b) = b let rw1'2 f (a,b) = f a,b let rw2'2 f (a,b) = a,f b let tupA2 = rw2'2 not tupA
type stat =
{count : int;
sum : int;
panic : bool;
}
let stat0 = {count=0; sum=0; panic=false}
let noPanic stat = {stat with panic=false}
let monitor stat n =
if n=999 then
{stat with panic=true}
else
{stat with count = stat.count + 1; sum = stat.sum + n}
// These records are labeled tuples.
// You can build them directly or from another record by replacing selected fields.
let dataset = [| 1;2;3;4;5;6;7;8;9;10 |] : int array
// Functional style - folds state through
let stat = Array.fold_left monitor stat0 dataset
type mstat =
{mutable mcount : int;
mutable msum : int;
mutable mpanic : bool;
}
let createStat0 () = {mcount=0; msum=0; mpanic=false}
let doNoPanic mstat = mstat.mpanic <- false
let doMonitor mstat n =
if n=999 then
mstat.mpanic <- true
else (
mstat.mcount <- mstat.mcount + 1;
mstat.msum <- mstat.msum + n
)
// The assignment operator is <-
// Note: assignment expression sequence - seperated by SEMI colons
// Note: brackets required for precedence reasons
// Imperative style - iterates and mutates state
let mstat = createStat0 ()
do
for i = 0 to Array.length dataset - 1 do
printf "Monitoring index = %d\n" i;
doMonitor mstat dataset.(i)
done
let xsA = [] // empty list
let xsB = 1 :: xsA // cons
let xsC = [1;2;3;4;5] @ xsB // append
let nxsA = List.length xsA
let ysC = List.map (fun i -> i*10) xsC
let sumXsC = List.fold_left (fun sum x -> sum+x) 0 xsC
let sumYsC = List.fold_left (fun sum x -> sum+x) 0 ysC
let xsD = List.filter (fun x -> x mod 2 = 1) xsC
let rec interleave xs ys =
match xs,ys with
x::xs,y::ys -> x::y::interleave xs ys
| [] ,ys -> ys
| xs ,[] -> xs
let xysC = interleave xsC ysC
F# has generic (polymorphic) arrays. In .NET 2.0, there is a generic array type (thanks don!). F# arrays are .NET arrays.
let arrA = [| 0;2;4;6;8 |] // array expressions
let arrB = Array.init 5 (fun i -> i*2) // initialisation calls
let arrC = Array.append [|0;2;4|] [|6;8|] // append
// MLLib.Array.* functions are ML-like functions
let lenArrA = Array.length arrA
let eltArrA = arrA.(0)
let sumArr arr = Array.fold_left (fun sum n -> sum + n) 0 arr
// .NET instance/static members usable
// Note, use of instance members require the type to be known.
let sumArr2 (arr : 'a array) =
let mutable sum = 0 in
for i = 0 to arr.Length - 1 do
sum <- sum + arr.(i)
done;
sum
// Array type can be written in ML or .NET style
let arrX = [| "Alpha"; "Beta" |] : string array
let arrY = [| "Alpha"; "Beta" |] : string[]
type colour =
| Red
| Green
| Blue
| RGB of float * float * float (* floats in [0,1] *)
| Alpha of float * colour (* float in [0,1] *)
Functions over datatypes by pattern matching
let rec redPart c = match c with
| Red -> 255.0
| Green -> 0.0
| Blue -> 0.0
| RGB (r,g,b) -> r
| Alpha (a,c) -> a * redPart c
Build a .NET System.Drawing.Color value
open System.Drawing
let int255 x = int_of_float (x * 255.0)
let rec color c = match c with
| Red -> Color.Red
| Green -> Color.Green
| Blue -> Color.Blue
| RGB (r,g,b) -> Color.FromArgb(int255 r,int255 g,int255 b)
| Alpha (a,c) -> Color.FromArgb(int255 a,color c)
There are two ways to create lambda expressions.
"fun ..." when there are no alternatives. "function ... | ..." when there are.
Note, precedence differs. You will mostly want to use "fun" for anonymous lambda expr.
// fun <pattern> -> <expr>
let inc = fun x -> x + 1
let incList = List.map inc
let xs = incList [1;2;3]
// function <pattern> -> <expr> | <pattern> -> <expr> | ...
let rotate = function
| [] -> []
| x::xs -> xs @ [x]
// sumList - versionA
let rec sumListA xs = match xs with
| [] -> 0
| x::xs -> x + sumListA xs
let sumListB xs = List.fold_left (fun sum x -> sum + x) 0 xs
let sumListC xs = List.fold_left (+) 0 xs
// NB: bracket infix op in order to use it as nonfix function
// eg: (+) (-) (&&&) but beware of "comment issues" for * !!
// The .NET types are also available.
open System.Net
let newsIPE = Dns.GetHostByName("news.bbc.co.uk") // Static method
let newsAddrs = newsIPE.AddressList // get property
// constructors - overload resolved statically
let ipA = new IPAddress( 0xd43ae235L ) // L suffix for int64 literal
let ipB = new IPAddress( [|212uy;58uy;226uy;53uy|] ) // uy suffix for byte literal
let ipLB = new IPAddress( 0x0100007fL )
let qA = IPAddress.IsLoopback(ipA) // static method "type.method(args)"
let qLB = IPAddress.IsLoopback(ipLB)
let absA = ipA.GetAddressBytes() // instance method
let addr = ipA.Address // get property
do ipB.Address <- 0x0100007fL // set property
let loopbackIP = IPAddress.Loopback // static field
let anyIP = IPAddress.Any
let parity n =
match n mod 2 with
| 0 -> "even"
| 1 -> "odd"
| n -> failwith "parity: dead code"