Skip to content

Instantly share code, notes, and snippets.

@MartinBodocky
Created April 4, 2014 14:47
Show Gist options
  • Save MartinBodocky/9976173 to your computer and use it in GitHub Desktop.
Save MartinBodocky/9976173 to your computer and use it in GitHub Desktop.
Chapter 4-6
//Mutable record types
open System
type MutableCar =
{
Make : string
Model : string
mutable Miles : int
}
let driveForAReason (car : MutableCar) : unit =
let rng = new Random()
car.Miles <- car.Miles + rng.Next() % 10000
let kitt = { Make = "Pontiac"; Model = "Trans Am"; Miles = 0}
driveForAReason kitt
kitt
//Unit of measures
[<Measure>]
type fahrenheit
let printTemperature (temp : float<fahrenheit>) =
if temp < 32.0<_> then
printfn "Bellow Freezing"
elif temp > 100.0<_> then
printfn "Hot!"
else
printfn "Scorching!"
let seatle = 59.0<fahrenheit>
printTemperature seatle
[<Measure>]
type celsius
let cambridge : float<celsius> = 18.0<celsius>
printTemperature cambridge
//Define measure for meter
[<Measure>]
type m
// Mutliplication
1.0<m> * 1.0<m>
//Division
1.0<m> / 1.0<m>
//Define seconds and hertz
[<Measure>]
type s
[<Measure>]
type Hz = s ^ -1
3.0<s^-1> = 3.0<Hz>
//Adding methods to unit of measures
[<Measure>]
type far =
static member ConvertToCel(x: float<far>) =
(5.0<cel> / 9.0<far>) * (x - 32.0<far>)
and [<Measure>] cel =
static member ConvertToFar (x: float<cel>) =
(9.0<far> / 5.0<cel> * x) + 32.0<far>
far.ConvertToCel(100.0<far>)
//UnitSymbols contains the abbreviated versions of SI units
open Microsoft.FSharp.Data.UnitSystems.SI.UnitSymbols
open Microsoft.FSharp.Data.UnitSystems.SI.UnitNames
//in candela
let flashlightIntensity = 80.0<cd>
let weightofyou = 85.0<kilogram>
//generic units of measure
let squareMeter (x : float<m>) = x*x
let genericSquare (x : float<_>) = x*x
squareMeter 1.0<m>
genericSquare 1.0<m/s>
//Represents a point respecting the unit of measure
type Point< [<Measure>] 'u> (x : float<'u>, y : float<'u>) =
member this.X = x
member this.Y = y
member this.UnitlessX = float x
member this.UnitlessY = float y
member this.Length =
let sqr x = x * x
sqrt <| sqr this.X + sqr this.Y
override this.ToString() =
sprintf "{%f, %f}" this.UnitlessX this.UnitlessY
let p = new Point<m>(10.0<m>, 10.0<m>)
p.Length
//using the array comprehension syntax
let perfectSquares = [| for i in 1..7 -> i * i |]
//manually decaled
let perfectSquares2 = [|12;321;434;656;787;|]
//indexing
perfectSquares2.[0]
//ROT 13 encryption in f#
open System
//Encrypt a letter using ROT13
let rot13Encrypt (letter : char) =
// Move the letter forward 13 places in the alphabet
if Char.IsLetter(letter) then
let newLetter =
(int letter)
|> (fun letterIdx -> letterIdx - (int 'A'))
|> (fun letterIdx -> (letterIdx + 13) % 26)
|> (fun letterIdx -> letterIdx + (int 'A'))
|> char
newLetter
else
letter
//Loop through each letter array element, encrypting each letter
let encryptText (text: char[]) =
for idx = 0 to text.Length - 1 do
let letter = text.[idx]
text.[idx] <- rot13Encrypt letter
let text = Array.ofSeq "THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG"
printfn "Original = %s" <| new String(text)
encryptText(text)
printfn "Encrypted = %s" <| new String(text)
//A unique trait of ROT13 is that to decrypt, simply encrypt again
encryptText(text)
printfn "Decrypted = %s"<| new String(text)
//Array slices
let daysOfWeek = Enum.GetNames(typeof<DayOfWeek>)
//Standard array slice, elements 2 through 4
daysOfWeek.[2..4]
//Just specify lower bound, elements 4 to the end
daysOfWeek.[4..]
//Just specify an upper bound, elements 0 to 2
daysOfWeek.[..2]
//Specify no bounds
daysOfWeek.[*]
// Initialize an array of sin-wave elements
let divisions = 4.0
let twoPi = 2.0 * Math.PI
Array.init(int divisions) (fun i -> float i * twoPi / divisions)
//Construct empty arrays
let emptyIntArray : int[] = Array.zeroCreate 3
let emptyStringArray : string[] = Array.zeroCreate 3
//Pattern matching in array
let describeArray arr =
match arr with
| null -> "The array is null"
| [| |] -> "The array is empty"
| [| x |] -> "The array has one element"
| [| x ; y|] -> "The array has two elements"
| a -> sprintf "The array has %d elements, %A" a.Length a
describeArray null
describeArray [||]
describeArray [|1..4|]
describeArray [| (12,3) |]
//array partition
let isGreaterThan x = (x>10)
[| 5.. 15 |] |> Array.partition isGreaterThan
// tryFind and tryFindIndex
let rec isPowerOfTwo x =
if x = 2 then
true
elif x % 2 = 1 then
false
else
isPowerOfTwo (x/2)
[| 1; 7; 13; 64; 32|] |> Array.tryFind isPowerOfTwo
[| 1; 7; 13; 64; 32|] |> Array.tryFindIndex isPowerOfTwo
// aggregate operators
let vowels = [| 'a'; 'e'; 'i'; 'o';'u' |]
Array.iteri (fun idx chr -> printfn "viwel.[%d] = %c" idx chr) vowels
//Rectangular arrays
// Create a 3x3 array
let idenityMatrix : float[,] = Array2D.zeroCreate 3 3
idenityMatrix.[0,0] <- 1.0
idenityMatrix.[1,1] <- 1.0
idenityMatrix.[2,2] <- 1.0
idenityMatrix
// Create a jagged array
let jaggedArray : int [][] = Array.zeroCreate 3
jaggedArray.[0] <- Array.init 1 (fun x -> x)
jaggedArray.[1] <- Array.init 2 (fun x -> x)
jaggedArray.[2] <- Array.init 3 (fun x -> x)
jaggedArray
//Create a List<_> of planets
open System.Collections.Generic
let planets = new List<string>()
planets.Add("Mercury")
planets.Add("Venus")
planets.Add("Earth")
planets.Add("Mars")
planets.Add("Pluto")
planets.AddRange([| "Neptune"; "Saturn"|])
planets.Count
planets.Remove("Pluto")
planets
//Using a dictionary
//Atom Mass Units
[<Measure>]
type amu
type Atom = {Name: string; Weight: float<amu>}
open System.Collections.Generic
let periodicTable = new Dictionary<string, Atom>()
periodicTable.Add("H", {Name = "Hydrogen";Weight = 1.0079<amu>})
periodicTable.Add("He", {Name = "Helium";Weight = 4.0026<amu>})
periodicTable.Add("Li", {Name = "Lithium";Weight = 6.9410<amu>})
periodicTable.Add("Be", {Name = "Beryllium";Weight = 9.0122<amu>})
periodicTable.Add("B", {Name = "Boron";Weight = 10.811<amu>})
//Lookup an element
let printElement name =
if periodicTable.ContainsKey(name) then
let atom = periodicTable.[name]
printfn "Atom with symbol '%s' has weight %A." atom.Name atom.Weight
else
printfn "Error. No atom found"
let printElement2 name =
let (found, atom) = periodicTable.TryGetValue(name)
if found then
printfn "Atom with symbol '%s' has weight %A." atom.Name atom.Weight
else
printfn "Error. No atom found"
// loops
for i=1 to 5 do printfn "%A" i
for i=5 downto 0 do printfn "%A" i
//for loops can do pattern matching :)
type Pet =
| Cat of string * int
| Dog of string
let famousPets = [ Dog("Lassie"); Cat("Felix",9); Dog "Rin Tin Tin"]
for Dog(name) in famousPets do
printfn "Dof : %s" name
// Pattern matching against types
let whatIs (x : obj) =
match x with
| :? string as s -> printfn "%s is string" s
| :? int as i -> printfn "%d is integer" i
| :? list<int> as l -> printfn "%A is list of integer" l
| _ -> printfn "%A is another type %A" x <| x.GetType().Name
whatIs [1..5]
whatIs "aaa"
whatIs 1212
whatIs 12.3<joule>
//Extend the System.Int32 AKA int type
type System.Int32 with
member this.ToHexString() = sprintf "0x%x" this
(1094).ToHexString()
type Point< [<Measure>] 'u> with
member this.ToMyLength() = this.Length
let app = p.ToMyLength()
app
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment