Successfully reported this slideshow.                             Upcoming SlideShare
×

The taste of F#

1,233 views

Published on

Walk through a solution to Advent of Code 2016 Day 8 problem, done in F# with immutable data structures and pure functions

Published in: Software
• Full Name
Comment goes here.

Are you sure you want to Yes No • Be the first to comment

• Be the first to like this

The taste of F#

1. 1. THE TASTE OF F#I am still Mikhail Shilkov You can nd me at @MikhailShilkov and http://mikhail.io
2. 2. FACTS ABOUT F# .NET language Functional First Open Source
3. 3.   0 1 2 3 4 5 6 7 8 9 x  0   # # # #  1   #         # #    2   # # #   # # # #  3   #         # #           4   #   y
4. 4. // 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
5. 5. // 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
6. 6. // 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
7. 7. 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  ...
8. 8. let Width = 10   // val Width : int = 10    let Height = 5   // val Height : int = 5
9. 9. 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
10. 10. 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
11. 11. Set.empty  Set.add element set  Set.filter predicate set  Set.union set1 set2  Set.map f set
12. 12. 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
13. 13. 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
14. 14. 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>
15. 15. let turnOn predicate screen =    fullScreen    |> Set.filter predicate    |> Set.union screen    // val turnOn : f:(int * int ‐> bool) ‐>  // screen:Set<int * int> ‐> Set<int * int>
16. 16. 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>
17. 17. 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
18. 18. let move f screen =    Set.map f screen    // val move :  //  f:('a ‐> 'b) ‐> screen:Set<'a> ‐> Set<'b>  //    when 'a : comparison and 'b : comparison
19. 19. 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
20. 20. 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
21. 21. 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
22. 22. type Instruction =    | Rect of width: int * height: int    | RotateRow of index: int * by: int    | RotateColumn of index: int * by: int
23. 23. 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>
24. 24. 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
25. 25. let solve2 instructions =   List.fold execute Set.empty instructions
26. 26. DEMO
27. 27. WHAT WE SAW Strong types, cheap to create Low overhead, no boilerplate Reusable patterns and data structures "The pit of functional success"
28. 28. THANKS!Mikhail Shilkov You can nd me at @MikhailShilkov and http://mikhail.io