THE TASTE OF
F#I am still Mikhail Shilkov
You can nd me at @MikhailShilkov and http://mikhail.io
FACTS ABOUT F#
.NET language
Functional First
Open Source
  0 1 2 3 4 5 6 7 8 9 x 
0   # # # # 
1   #         # #   
2   # # #   # # # # 
3   #         # #          
4   #  
y
// rect AxB  
// 
// turns on all of the pixels in a rectangle  
// at the top‐left which is A wide and B tall 
// 
// e.g. rect 3x2:
  0 1 2 3 4 5 6 7 8 9 x 
0 
1        
2             
3                   
4  
y
  0 1 2 3 4 5 6 7 8 9 x 
0 # # # 
1 # # #     
2             
3                   
4  
y
// rotate row y=A by B  
// 
// shifts (with cycle) all of the pixels  
// in row A right by B pixels 
// 
// e.g. rotate row y=1 by 2
  0 1 2 3 4 5 6 7 8 9 x 
0 # # # 
1 # # #     
2             
3                   
4  
y
  0 1 2 3 4 5 6 7 8 9 x 
0 # # # 
1     # # #     
2             
3                   
4  
y
// rotate column x=A by B  
// 
// shifts (with cycle) all of the pixels  
// in column A down by B pixels 
// 
// e.g. rotate column x=2 by 4
  0 1 2 3 4 5 6 7 8 9 x 
0 # # # 
1     # # #     
2             
3                   
4  
y
  0 1 2 3 4 5 6 7 8 9 x 
0 # # # 
1       # #     
2             
3                   
4     # 
y
rect 1x1 
rotate row y=0 by 5 
rect 1x1 
rotate row y=0 by 6 
rect 1x1 
rotate row y=0 by 5 
rect 1x1 
rotate row y=0 by 2 
rect 1x1 
rotate row y=0 by 5 
rect 2x1 
rotate row y=0 by 2 
rect 1x1 
...
let Width = 10  
// val Width : int = 10 
 
let Height = 5  
// val Height : int = 5
type Pixel = int * int 
 
let pixel = (5, 2)  
// val pixel : int * int = (5, 2)
  0 1 2 3 4 5 6 7 8 9 x 
0  
1  
2           # 
3  
4  
y
type Screen = Set<Pixel> 
 
let screen = set [ (2, 1); (5, 2); (8, 3) ] 
// val screen : Set<int * int> = set [(2, 1); ...]
  0 1 2 3 4 5 6 7 8 9 x 
0 
1     #  
2           # 
3                 # 
4  
y
Set.empty 
Set.add element set 
Set.filter predicate set 
Set.union set1 set2 
Set.map f set
let emptyScreen = Set.empty 
 
let fullScreen =  
  seq { for x in 0..Width‐1 do  
        for y in 0..Height‐1 ‐> x, y } 
  |> Set.ofSeq
  0 1 2 3 4 5 6 7 8 9 x 
0 
1        
2             
3                   
4  
y
  0 1 2 3 4 5 6 7 8 9 x 
0 # # # # # # # # # # 
1 # # # # # # # # # # 
2 # # # # # # # # # # 
3 # # # # # # # # # # 
4 # # # # # # # # # # 
y
let turnOnOne (x, y) screen = 
  Set.add (x, y) screen 
 
// val turnOnOne : 
//  x:'a * y:'b ‐> screen:Set<'a * 'b> ‐> Set<'a * 'b> 
//    when 'a : comparison and 'b : comparison 
 
let screen2 = turnOnOne (1, 4) screen
  0 1 2 3 4 5 6 7 8 9 x 
0 
1     #  
2           # 
3                 # 
4  
y
  0 1 2 3 4 5 6 7 8 9 x 
0 
1     #  
2           # 
3                 # 
4   # 
y
let turnOn predicate screen = 
  let filtered = Set.filter predicate fullScreen 
  Set.union screen filtered 
 
// val turnOn : f:(int * int ‐> bool) ‐> 
// screen:Set<int * int> ‐> Set<int * int>
let turnOn predicate screen = 
  fullScreen 
  |> Set.filter predicate 
  |> Set.union screen 
 
// val turnOn : f:(int * int ‐> bool) ‐> 
// screen:Set<int * int> ‐> Set<int * int>
let turnOnRect (xmin, ymin) (xmax, ymax) screen = 
  let isInRect (x, y) =  
    x >= xmin && x <= xmax  
    && y >= ymin && y <= ymax 
  turnOn isInRect screen 
 
// val turnOnRect : 
//  xmin:int * ymin:int ‐> xmax:int * ymax:int ‐> 
//    screen:Set<int * int> ‐> Set<int * int>
let screen3 = turnOnRect (2, 1) (3, 4) screen2 
 
// val screen3 : Set<int * int> = set [ ... ]
  0 1 2 3 4 5 6 7 8 9 x 
0 
1     #  
2           # 
3                 # 
4   # 
y
  0 1 2 3 4 5 6 7 8 9 x 
0 
1     # # 
2     # #   # 
3     # #         # 
4   # # # 
y
let move f screen = 
  Set.map f screen 
 
// val move : 
//  f:('a ‐> 'b) ‐> screen:Set<'a> ‐> Set<'b> 
//    when 'a : comparison and 'b : comparison
let rotateRow index by screen = 
  let mapAt (x, y) = 
    if y = index then (x + by) % Width, y  
    else x, y   
  move mapAt screen 
 
// val rotateRow : 
//   index:'a ‐> by:int ‐>  
//     screen:Set<int * 'a> ‐> Set<int * 'a> 
//       when 'a : comparison
let screen4 = rotateRow 3 2 screen3 
 
// val screen4 : Set<int * int> = set [ ... ]
  0 1 2 3 4 5 6 7 8 9 x 
0 
1     # # 
2     # #   # 
3     # #         # 
4   # # # 
y
  0 1 2 3 4 5 6 7 8 9 x 
0 
1     # # 
2     # #   # 
3 #       # #         
4   # # # 
y
let rotateColumn index by screen = 
  let mapAt (x, y) = 
    if x = index then x, (y + by) % Height  
    else x, y   
  move mapAt screen 
 
// val rotateColumn : 
//   index:'a ‐> by:int ‐>  
//     screen:Set<int * 'a> ‐> Set<int * 'a> 
//       when 'a : comparison  
type Instruction = 
  | Rect of width: int * height: int 
  | RotateRow of index: int * by: int 
  | RotateColumn of index: int * by: int
let execute screen instruction =  
  match instruction with 
  | Rect (w, h) ‐> turnOnRect (0, 0) (w‐1, h‐1) screen 
  | RotateRow (i, by) ‐> rotateRow i by screen 
  | RotateColumn (i, by) ‐> rotateColumn i by screen
 
// val execute : 
//   screen:Set<int * int> ‐> instruction:Instruction  
//   ‐> Set<int * int>
let rec step screen instructions = 
  match instructions with 
  | [] ‐> screen 
  | instruction :: others ‐>  
    let newScreen = execute screen instruction 
    step newScreen others 
 
let solve1 instructions =  
  step Set.empty instructions
let solve2 instructions = 
 List.fold execute Set.empty instructions
DEMO
WHAT WE SAW
Strong types, cheap to create
Low overhead, no boilerplate
Reusable patterns and data structures
"The pit of functional success"
THANKS!Mikhail Shilkov
You can nd me at @MikhailShilkov and http://mikhail.io

The taste of F#