Skip to content

Instantly share code, notes, and snippets.

@rranelli
Created April 17, 2014 21:22
Show Gist options
  • Select an option

  • Save rranelli/11012392 to your computer and use it in GitHub Desktop.

Select an option

Save rranelli/11012392 to your computer and use it in GitHub Desktop.
(* Fsharp files must contain a module definition, which is equivalent to a namespace *)
module FsharpHighlights
#light
(* The open statement is equivalent to c#'s using and vb's imports *)
open System
(* Functions are first class citizens ;D *)
let square x = x * x
let numbers x = [1..x]
(* composition can be made using the pipeArrow operator *)
let squares x = x |> numbers |> List.map square
(* you can also compose functions using the usual pattern *)
let squares2 x = List.map square (numbers x)
(* sequences are nice, just like lists but lazily evaluated *)
let seq = {1..10}
(* you can use pattern matching in such a nice way ;D *)
let (x,y) = (1,2)
(* records are also quite nice, but you have to define them first as a type *)
type coord = { X : float; Y : float }
let myRecord = {X = 1.0; Y = 2.0}
(* pattern matching everywere. *)
let myHead :: theTail = [1; 2; 3; 4] // Note the compiler warning for non-exaustive pattern matching
(* function definitions are made using let expressions. This makes functions even less special *)
let rec facto = function
| 0 -> 1
| n -> n * facto (n - 1)
(* List Comprehensions are AWESOME *)
let listcomprehended = [for x in 1..10 do if x % 2 = 0 then yield facto x]
(* the construct let (functionName) = function {| pattern -> expr}+ is equivalent to ml's and erlang's
multiple function entrypoints *)
let rec all_except = function
| (_, []) -> []
| (s1, head :: tail) -> if head = s1
then tail
else head :: all_except (s1, tail)
(* option types are nice *)
let safediv x y = match y with
| 0 -> None
| _ -> Some(x / y)
let safelyDivided = safediv 33 0;;
(* you can also use currying for function definitions,
but you lose the shorthand syntax of multiple entrypoints obviusly *)
let rec all_except_curried x xlist =
match xlist with
| [] -> []
| head :: tail -> if head = x
then tail
else head :: tail
(* Tagged unions do amor! *)
type quadrant = Origin | I | II | III | IV
(* pattern matching with records *)
let getQuadrant = function
| {X = 0.0 ; Y = 0.0; } -> Origin
| item when item.X >= 0.0 && item.Y >= 0.0 -> I
| item when item.X <= 0.0 && item.Y >= 0.0 -> II
| item when item.X <= 0.0 && item.Y <= 0.0 -> III
| item when item.X >= 0.0 && item.Y <= 0.0 -> IV
| item -> raise (System.ArgumentException (String.Format ("Invalid Argument {0}", item))); // Exceptions are subtypes of it all
(* Tagged/Discriminated unions can be used nicely the same way value objects are used *)
type expr = Add of expr * expr | Const of int | Mult of expr * expr | Var of string
type switchstate = On | Off | Adjustable of float
let toggle = function
| On -> Off
| Off -> On
| Adjustable brightness ->
let pivot = 0.5 in if brightness <= pivot
then Adjustable (brightness + pivot)
else Adjustable (brightness - pivot)
(* Tagged unions are the most beautifull trees you will ever see *)
type 'a bintree = Leaf of 'a | Node of 'a bintree * 'a bintree
let simpleTree = Node (
Leaf 1,
Node (
Leaf 2,
Node (
Node (
Leaf 4,
Leaf 5
),
Leaf 3
)
)
)
let countLeaves tree =
let rec loop sum = function
| Leaf _ -> sum + 1
| Node (tree1, tree2) -> sum + (loop 0 tree1) + (loop 0 tree2)
in
loop 0 tree
(* Propositional logic in a extremely concise manner *)
type proposition =
| True
| False
| Not of proposition
| And of proposition * proposition
| Or of proposition * proposition
let rec eval = function
| True -> true
| False -> false
| Not prop -> not (eval prop)
| And (prop1, prop2) -> eval prop1 && eval prop2
| Or (prop1, prop2) -> eval prop1 || eval prop2
(* The distinction between classes and types now is kinda not existant.
Fuction's as first class are THE thing *)
type Account (number, holder) =
let mutable amount = 0m
member x.Number
with get() = number
member x.Holder
with get() = holder
member x.Amount
with get() = amount
member x.Deposit value = amount <- amount + value
member x.Withdraw value = amount <- amount - value
let homer = new Account (12345, "Homer")
let marge = new Account (67890, "Marge")
(* This function is shit. Returns Unit and sideeffects *)
let transfer amount (source: Account) (target: Account) =
source.Withdraw amount
target.Deposit amount
(* Inheritance and pattern matching for the win*)
type Person (name) =
member x.Name = name
abstract Greet : unit -> unit
default x.Greet() = printfn "Hi, I'm %s" x.Name
type Student (name, studentId : int) =
inherit Person (name)
let mutable _GPA = 0.0
member x.StudentID = studentId
member x.GPA
with get() = _GPA
and set value = _GPA <- value
type Worker (name, employer) =
inherit Person (name)
let mutable _salary = 0.0
member x.Salary
with get() = _salary
and set value = _salary <- value
member x.Employer = employer
type Quebecois (name) =
inherit Person (name)
override x.Greet() = printfn "Bonjour, je m'apelle %s, eh" x.Name
(*You can see that subtyping works wonders *)
let astudent : Student = new Student ("myname", 1235)
let handlesStuff (person : Person) =
match person with
| :? Student as student -> printfn "I am a student"
| :? Quebecois as quebecois -> printfn "I be quebecois"
| :? Worker as worker -> printfn "%A" worker.Name
| _ -> printfn "I don't recognize type '%s'" (person.GetType().Name)
let aperson = astudent
let () = handlesStuff aperson
let (somePerson, someStudent, someWorker) as triplz =
((new Person "Juliet"), (new Student ("Monique", 123456)), (new Worker ("Carla", "Awesome Hair Salon")))
// also, check that the trp parameter in tripleHandling must have type Person*Person*Person. No need to declare, but the compiler knows it all.
let tripleHandling trp =
match trp with
| (x,y,z) -> handlesStuff x
handlesStuff y
handlesStuff z
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment