val register : name:string -> age:int -> unit Full name: index.register
val name : string
val age : int
val printf : format:Printf.TextWriterFormat<'T> -> 'T Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printf
Multiple items val string : value:'T -> string Full name: Microsoft.FSharp.Core.Operators.string -------------------- type string = System.String Full name: Microsoft.FSharp.Core.string
Multiple items val int : value:'T -> int (requires member op_Explicit) Full name: Microsoft.FSharp.Core.Operators.int -------------------- type int = int32 Full name: Microsoft.FSharp.Core.int -------------------- type int<'Measure> = int Full name: Microsoft.FSharp.Core.int<_>
type unit = Unit Full name: Microsoft.FSharp.Core.unit
Multiple items module List from Microsoft.FSharp.Collections -------------------- type List<'T> = | ( [] ) | ( :: ) of Head: 'T * Tail: 'T list interface IEnumerable interface IEnumerable<'T> member GetSlice : startIndex:int option * endIndex:int option -> 'T list member Head : 'T member IsEmpty : bool member Item : index:int -> 'T with get member Length : int member Tail : 'T list static member Cons : head:'T * tail:'T list -> 'T list static member Empty : 'T list Full name: Microsoft.FSharp.Collections.List<_>
val iter : action:('T -> unit) -> list:'T list -> unit Full name: Microsoft.FSharp.Collections.List.iter
val printfn : format:Printf.TextWriterFormat<'T> -> 'T Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val sprintf : format:Printf.StringFormat<'T> -> 'T Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
val map : mapping:('T -> 'U) -> list:'T list -> 'U list Full name: Microsoft.FSharp.Collections.List.map
val set : elements:seq<'T> -> Set<'T> (requires comparison) Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.set
Multiple items val seq : sequence:seq<'T> -> seq<'T> Full name: Microsoft.FSharp.Core.Operators.seq -------------------- type seq<'T> = System.Collections.Generic.IEnumerable<'T> Full name: Microsoft.FSharp.Collections.seq<_>
val filter : predicate:('T -> bool) -> list:'T list -> 'T list Full name: Microsoft.FSharp.Collections.List.filter
module Seq from Microsoft.FSharp.Collections
val iter : action:('T -> unit) -> source:seq<'T> -> unit Full name: Microsoft.FSharp.Collections.Seq.iter
val unfold : generator:('State -> ('T * 'State) option) -> state:'State -> seq<'T> Full name: Microsoft.FSharp.Collections.Seq.unfold
union case Option.Some: Value: 'T -> Option<'T>
val take : count:int -> source:seq<'T> -> seq<'T> Full name: Microsoft.FSharp.Collections.Seq.take
Functionland
A Romance of Many Paradigms
by @troykershaw
(Press 's' to read the story)
ZZZZzzzz....
"Wake up!" you hear your mum yell. "You'll be late for the hackathon!"
You roll over and peer at your clock. It's 8.42, only 18 minutes shy of Functionland's annual hackathon! The hackathon gives students the chance to win a place at the prestigous Functionland Knight Academy.
Your heart swells with a distinct feeling of global pride as you think about Functionland, the only home you have ever known. Selection for the Functionland Knight Academy would be an honour beyond description.
You quickly put on your favourite f# shirt and hurry to the contest.
"Don't forget to pack FSI" your mum yells after you.
Pack your bag
Check that FSI is running on your machine.
Beginner
Learn all about values
Intermediate
Help your fellow devs :)
BAM!
As you tear down the street to the hackathon venue, you clumsily lose your footing and bowl head first into a woman. A gorgeous woman, at that. Red-faced from a combination of exertion and embarrassment, you stumble to your feet and stick out a grazed arm for the woman to grasp. You soon see that there's no need: she's already on her feet, looking fresh-faced and a little amused.
"Keen to get hacking, I see" she quips, before disappearing down the road.
You groan inwardly, torn between desperately wanting to see the woman again and hoping to avoid further humiliation by never seeing her again.
When you finally turn up at registration you are told:
Please write a function that takes your name and age and prints them to the console.
Intermediate
Print your name in extravagant ASCII art
Advanced
Do intermediate, but make it print character by character as though it's being typed by a typewriter
Show how to print to the console
Show how a function works
Discuss type inference
Registration
1:
2:
3:
let register name age =
printf "Name: %s ; Age %d " name age
register "Link" 14
1:
2:
3:
Name : Link ; Age 14
val register : name : string -> age : int -> unit
val it : unit = ()
King Alonzo speaks
The King of Functionland rises to address the would-be hackers.'
"Welcome to the annual Functionland hackathon. This is where the best and brightest are given the ' opportunity to prove themselves worthy to train with the Knight Academy.
"There is just one rule."
No mutability!
"This year, the problem you need to solve to win the coveted prize is:"
FizzBuzz
You must print the numbers 1 to 100 in the console, however,
if the number is divisible by 3, print "Fizz",
if it is divisible by 5, print "Buzz",
if it is divisible by 3 and 5, print "FizzBuzz"
Intermediate
Use active patterns
Advanced
Play "FizzBuzzWoof" where "Woof" is divisible by 7. You must print "Fizz", "Buzz" or "Woof" if any number contains or is divisible by 3, 5 or 7. Words must be printed in the order given in the title.
You have 2 minutes to check your notes before we start
- look at list generation
- look at pattern matching
Cheat sheet
You quickly look up your notes.
"Okay - what elements do I need here?"
1:
2:
for i = 1 to 100 do
printf "%d" i
1:
2:
[1.. 100 ]
|> List . iter (fun n -> .. . )
1:
2:
3:
match number with
| n when n > 0 -> printfn "Greater than 0"
| n -> printfn "Less than or equal to 0"
Ding! Ding!
"It looks like someone has solved the problem," the king says. "Please git push your code to me."
FizzBuzz
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
let mutable i = 0
while i < 101 do
let mutable str = ""
if i % 3 = 0 then
str <- str + "Fizz"
if i % 5 = 0 then
str <- str + "Buzz"
if str = "" then
str <- string i
printf "%s" str
i <- i + 1
"Close, but you're mutating" the king says. "The competition is still on!"
FizzBuzz
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
let fizzBuzz number =
match number with
| n when n % 15 = 0 -> "FizzBuzz"
| n when n % 3 = 0 -> "Fizz"
| n when n % 5 = 0 -> "Buzz"
| n -> sprintf "%d" n
[1.. 100 ]
|> List . map fizzBuzz
|> List . iter (printfn "%s" )
You finish your solution and quickly push your code to the King.
"We have a winner!" the King announces. "Come up and claim your prize."
You grip your chair, preparing to rise, but stop dead in your tracks when the King says: "Today's fastest ' problem solver is none other than my daughter, Princess Quinn!"
As the Princess takes the stage, you gasp: it's the woman from the street!
Princess Quinn faces her crowd of admirers and bows her head, preparing to receive the winner's medal. At that moment, the earth begins to tremble. A gaping hole forms right below the Princess and she is pulled inside. An evil looking man, dressed entirely in black, rises from the hole, grasping the terrified princess in his bony arms.
The Kidnapping
"Be warned, smug Functionlanders: I shall soon rule your world!" With a snarl, he disappears down the hole, taking the flailing Princess with him.
In desperation, you launch yourself after her, but your body is thrown back by a force field now covering the hole.
The Functionland knights appear, examining the area and assessing the unexpected turn of events.
Concerned but composed, the King stands up to address the gathering.
"The man that took my daughter is the ruler of Imperativeland: a dark world whose inhabitants are imprisoned by imperative principles. We believe that he is now trying to take over our world and kidnapping the Princess will give him the power to do so.
"The hole is a portal to Imperativeland. The force field covering it appears to be locked by an ancient, unknown sequence. The knights believe that once the force field is unlocked, there will only be enough time for one person to pass through the portal before it seals again.
We are calling for everyone to prepare themselves to rescue the Princess by attempting to solve the ancient sequence."
You race to the King, eager to rescue the brilliant Princess.
"Wait", the King says. "You can't enter Imperativeland without a sword and shield. Go and see the Knight Commander and he will help you prepare."
You run to the Knight Commander.
Knight Commander
1:
type NewRecord = { Property1 : string ; Property2 : int }
"So you need a sword and shield, do you?" says the Knight Commander.
"Well, with everything that's been going on, we're all out of weapons and armour. You're going to have to make your own. Do you need a refresher?"
"Okay, you define a record like this." [show fragment]
A siren goes off.
"Sorry, I need to see what that's about. You'll have to figure the rest out on your own."
Sword and Shield
Create two records, Sword and Shield .
A Sword should have Damage and Durability properties.
A Shield should have Protection and Durability properties.
Then create an instance of a sword and shield using these types.
Intermediate
Create a person record and attach the sword and shield
Advanced
Same as intermediate but make new weapons and armour that can replace the sword and shield easily
Sword and shield
1:
2:
3:
4:
5:
type Sword = { Damage : int ; Durability : int }
type Shield = { Protection : int ; Durability : int }
let sword = { Damage = 10 ; Durability = 1000 }
let shield = { Protection = 5 ; Durability = 500 }
Armed with your sword and shield, you set off to find the King.
All of a sudden, you feel strangely dizzy. Then everything goes black.
You wake up to find yourself imprisoned in some sort of cell. On the other side of the bars you spy a handful of your hackathon competitors.
"Welcome back" one of them sneers. "I'm afraid you were getting too close. We had no choice but to stop you. Enjoy yourself here and please excuse us - we're off to rescue the Princess!"
And with that, they leave.
You look around and see a keypad mounted on a wall just oustide the cell door. The keypad appears to unlock the cell. You can just reach it.
Escape from prison
The code appears to require 4 digits.
You see fingerprints on the numbers 0, 4, 7 and 9.
What are the combinations you need to try?
Beginner
Let's work this out together
Advanced
Find all the possible combinations
Expert
Find all the possible combinations for 'n' digits
Escape from prison
1:
2:
3:
4:
5:
6:
7:
let possibilities = [0 ; 4 ; 7 ; 9 ]
for i in possibilities do
for j in possibilities do
for k in possibilities do
for l in possibilities do
if i <> j && i <> k && i <> l && j <> k && j <> l && k <> l then
printfn "%d %d %d %d" i j k l
Here's an imperative way to solve the problem.
Escape from prison
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
let rec combinations acc set = seq {
match set with
| [] -> yield acc
| s ->
for n in s do
yield!
set
|> List . filter (fun s -> s <> n )
|> combinations (n :: acc )
}
[0 ; 4 ; 7 ; 9 ]
|> combinations []
|> Seq . iter (printfn "%A" )
And something a little more functional.
The cell door swings open, you grab your sword and shield and you set off again for the King.
"What took you so long?" cries the King in distress. "No one has unlocked the force field yet!"
As you near the force field, a knight approaches you with a screen.
"We've determined that the force field is based on some ancient sequence called Fibonacci. Our top mathematicians think that you need to enter in 50 values."
Print the first 50 numbers in the Fibonacci sequence.
The Fibonacci sequence is generated by adding the previous two terms.
By starting with 1 and 2, the first 10 terms will be:
1:
1 , 2 , 3 , 5 , 8 , 13 , 21 , 34 , 55 , 89 , .. .
Intermediate
Use an infinite sequence
Advanced
Play code golf
Fibonacci sequence
1:
2:
3:
4:
5:
let fibSeq = (1L ,1L ) |> Seq . unfold (fun (a , b ) -> Some (b , (b , a + b )) )
fibSeq
|> Seq . take 50
|> Seq . iter (printfn "%d" )
The force field jitters and disappears. You step in and...