hiking through the functional forest with fizz buzz
TRANSCRIPT
Hiking through the Functional Forest with FizzBuzz
Mike Harris | @MikeMKH | comp-phil.blogspot.com
let itinerary n = match n with | 0 -> "Rules" | 1 -> "Pattern Matching" | 2 -> "Types" | 3 -> "Higher Order Functions" | _ -> "Farewell"
// val itinerary : n:int -> string
let itinerary n = match n with | 0 -> "Rules" | 1 -> "Pattern Matching" | 2 -> "Types" | 3 -> "Higher Order Functions" | _ -> "Farewell" itinerary 0
// val it : string = “Rules"
Rules
• x | 3 and x | 5 => FizzBuzz
• x | 3 => Fizz
• x | 5 => Buzz
• x => string x
Specific
General
let fizzbuzzer x = if x % 15 = 0 then "FizzBuzz" elif x % 3 = 0 then "Fizz" elif x % 5 = 0 then "Buzz" else string x
Conditional
F#
let itinerary n = match n with | 0 -> "Rules" | 1 -> "Pattern Matching" | 2 -> "Types" | 3 -> "Higher Order Functions" | _ -> "Farewell" itinerary 1
// val it : string = “Pattern Matching"
let fizzbuzzer x = match x with | x when x % 15 = 0 -> "FizzBuzz"
| x when x % 3 = 0 -> "Fizz"
| x when x % 5 = 0 -> "Buzz"
| _ -> string x
Pattern Match
F#
let fizzbuzzer x = match x % 3, x % 5 with | 0, 0 -> "FizzBuzz" | 0, _ -> "Fizz" | _, 0 -> "Buzz" | _ -> string x
Pattern Matchwith Tuples
F#
let fizzbuzzer x = match x % 3 = 0, x % 5 = 0 with | false, false -> string x | false, true -> "Buzz" | true, false -> "Fizz" | true, true -> "FizzBuzz"
Pattern Matchwith Tuples
F#
let itinerary n = match n with | 0 -> "Rules" | 1 -> "Pattern Matching" | 2 -> "Types" | 3 -> "Higher Order Functions" | _ -> "Farewell" itinerary 2
// val it : string = “Types"
type FizzBuzzer = | FizzBuzz | Fizz | Buzz | Other of int
let fizzbuzzing x = match x % 3 = 0, x % 5 = 0 with | true, true -> FizzBuzz | true, false -> Fizz | false, true -> Buzz | false, false -> Other(x)
let fizzbuzzer x = match fizzbuzzing x with | FizzBuzz -> "FizzBuzz" | Fizz -> "Fizz" | Buzz -> "Buzz" | Other(x) -> string x
DiscriminatedUnion
F#
type FizzBuzzer = | FizzBuzz | Fizz | Buzz | Other of int
let fizzbuzzing x = match x % 3 = 0, x % 5 = 0 with | true, true -> FizzBuzz | true, false -> Fizz | false, true -> Buzz | false, false -> Other(x) … Discriminated
Union
F#
… let fizzbuzzing x = match x % 3 = 0, x % 5 = 0 with | true, true -> FizzBuzz | true, false -> Fizz | false, true -> Buzz | false, false -> Other(x)
let fizzbuzzer x = match fizzbuzzing x with | FizzBuzz -> "FizzBuzz" | Fizz -> "Fizz" | Buzz -> "Buzz" | Other(x) -> string x Discriminated
Union
F#
… let fizzbuzzer x = match fizzbuzzing x with | FizzBuzz -> "FizzBuzz" | Fizz -> "Fizz" | Buzz -> "Buzz" | Other(x) -> string x
DiscriminatedUnion
F#
type FizzBuzzer = | FizzBuzz | Fizz | Buzz | Other of int
let fizzbuzzing x = match x % 3 = 0, x % 5 = 0 with | true, true -> FizzBuzz | true, false -> Fizz | false, true -> Buzz | false, false -> Other(x)
let fizzbuzzer x = match fizzbuzzing x with | FizzBuzz -> "FizzBuzz" | Fizz -> "Fizz" | Buzz -> "Buzz" | Other(x) -> string x
DiscriminatedUnion
F#
let (|FizzBuzz|Fizz|Buzz|Other|) x = match x % 3 = 0, x % 5 = 0 with | true, true -> FizzBuzz | true, false -> Fizz | false, true -> Buzz | false, false -> Other(x)
let fizzbuzzer x = match x with | FizzBuzz -> "FizzBuzz" | Fizz -> "Fizz" | Buzz -> "Buzz" | Other(x) -> string x Complete
Active Pattern
F#
let (|FizzBuzz|Fizz|Buzz|Other|) x = match x % 3 = 0, x % 5 = 0 with | true, true -> FizzBuzz | true, false -> Fizz | false, true -> Buzz | false, false -> Other(x) …
CompleteActive Pattern
F#
… let fizzbuzzer x = match x with | FizzBuzz -> "FizzBuzz" | Fizz -> "Fizz" | Buzz -> "Buzz" | Other(x) -> string x
CompleteActive Pattern
F#
let (|FizzBuzz|Fizz|Buzz|Other|) x = match x % 3 = 0, x % 5 = 0 with | true, true -> FizzBuzz | true, false -> Fizz | false, true -> Buzz | false, false -> Other(x)
let fizzbuzzer x = match x with | FizzBuzz -> "FizzBuzz" | Fizz -> "Fizz" | Buzz -> "Buzz" | Other(x) -> string x Complete
Active Pattern
F#
let (|DivisibleBy|_|) divisor x = if x % divisor = 0 then Some () else None
let fizzbuzzer x = match x with | DivisibleBy 3 & DivisibleBy 5 -> "FizzBuzz" | DivisibleBy 3 -> "Fizz" | DivisibleBy 5 -> "Buzz" | _ -> string x Partial
Active Pattern
F#
let (|DivisibleBy|_|) divisor x = if x % divisor = 0 then Some () else None …
PartialActive Pattern
F#
… let fizzbuzzer x = match x with | DivisibleBy 3 & DivisibleBy 5 -> “FizzBuzz"
| DivisibleBy 3 -> “Fizz"
| DivisibleBy 5 -> “Buzz"
| _ -> string xPartialActive Pattern
F#
let (|DivisibleBy|_|) divisor x = if x % divisor = 0 then Some () else None
let fizzbuzzer x = match x with | DivisibleBy 3 & DivisibleBy 5 -> "FizzBuzz" | DivisibleBy 3 -> "Fizz" | DivisibleBy 5 -> "Buzz" | _ -> string x Partial
Active Pattern
F#
let itinerary n = match n with | 0 -> "Rules" | 1 -> "Pattern Matching" | 2 -> "Types" | 3 -> "Higher Order Functions" | _ -> "Farewell" itinerary 3
// val it : string = “Higher Order Functions"
let fizzbuzzer x = let rule d s = (fun x -> if x % d = 0 then s else "")
[rule 3 "Fizz"; rule 5 "Buzz"] |> List.fold (fun m f -> m + f x) "" |> (fun s -> if s = "" then string x else s)Fold
F#
let fizzbuzzer x = let rule d s = (fun x -> if x % d = 0 then s else "")
[rule 3 "Fizz"; rule 5 "Buzz"] |> List.fold (fun m f -> m + f x) "" |> (fun s -> if s = "" then string x else s)Fold
F#
function
result i
result ii
result iii
result p
value 1
value 2
value 3
value n
value a
value b
value c
value m
let fizzbuzzer x = let rec fizz = seq { yield "Fizz"; yield ""; yield ""; yield! fizz }
let rec buzz = seq { yield "Buzz"; yield ""; yield ""; yield ""; yield ""; yield! buzz } Seq.map2 (+) fizz buzz |> Seq.item (abs x) |> (fun s -> if s = "" then string x else s)
Zip
F#
… let rec fizz = seq { yield "Fizz"; yield ""; yield ""; yield! fizz }
let rec buzz = seq { yield "Buzz"; yield ""; yield ""; yield ""; yield ""; yield! buzz } …
Zip
F#
let fizzbuzzer x = let rec fizz = seq { yield "Fizz"; yield ""; yield ""; yield! fizz }
let rec buzz = seq { yield "Buzz"; yield ""; yield ""; yield ""; yield ""; yield! buzz } Seq.map2 (+) fizz buzz |> Seq.item (abs x) |> (fun s -> if s = "" then string x else s)
Zip
F#
let itinerary n = match n with | 0 -> "Rules" | 1 -> "Pattern Matching" | 2 -> "Types" | 3 -> "Higher Order Functions" | _ -> "Farewell" itinerary 4
// val it : string = “Farewell"
— Friedrich Nietzsche trans. R.J. Hollingdale,Human, All Too Human, “The Wanderer and His Shadow”, 324
“How can anyone become a thinker if he does not spend at least a third of the day without
passions, people, and books?”
Images• Klamath National Forest, NFS road 16N05 about 8 miles South of Happy Camp, California.
Taken by Erik Wheaton, http://www.burningwell.org/gallery2/v/Landscapes/forrests/16N05_March_05.jpg.html
• View of São Paulo city from Núcleo Pedra Grande in Cantareira State Park. From https://commons.wikimedia.org/wiki/File:Vista_de_s%C3%A3o_paulo_cantareira.jpg
• Centro de São Paulo, Brasil. Taken by Ana Paula Hirama, https://commons.wikimedia.org/wiki/File:Centro_SP2.jpg
• F# logomark, by Unknown at the source. Fair use, https://en.wikipedia.org/w/index.php?curid=44014320
• Lao-Tzu, by Lawrencekhoo - http://www.eng.taoism.org.hk/daoist-beliefs/immortals&immortalism/, Public Domain, https://commons.wikimedia.org/w/index.php?curid=3991827
• Friedrich Nietzsche, by Unknown - http://ora-web.swkk.de/nie_brief_online/nietzsche.digitalisate?id=234&nr=1, Public Domain, https://commons.wikimedia.org/w/index.php?curid=95964
• Me at StrangeLoop 2014. Taken by Kelsey Harris.
Source Code
• Conditional https://gist.github.com/MikeMKH/9866f9923fa4dfa140e6
• Pattern Matching https://gist.github.com/MikeMKH/3fe93b2feea575f075fc54aecff2f01c
• Pattern Matching with Tuple https://gist.github.com/MikeMKH/9b35eb70ffdbcb605efa
• Pattern Matching with Tuple using True / False https://gist.github.com/MikeMKH/f0d7f21554500ffc4de60d6acefca4a5
Source Code
• Discriminated Union https://gist.github.com/MikeMKH/05d95775276744c304d2e4e253960aba
• Complete Active Pattern https://gist.github.com/MikeMKH/15a837dbb24053320abb
• Partial Active Pattern https://gist.github.com/MikeMKH/a38be4d25641980a8dda
Source Code
• Foldhttps://gist.github.com/MikeMKH/39dbbc94d963df436c62
• Ziphttps://gist.github.com/MikeMKH/c107d578d727ba514d05fc8bfa078bb7
Books
• Brandewinder, Mathias. Machine learning projects for .NET Developers. Berkeley, CA New York, NY: Apress, 2015. Print.
• Fancher, Dave. The book of F♯ : breaking free with managed functional programming. San Francisco: No Starch Press, 2014. Print.
• Lipovača, Miran. Learn you a Haskell for great good! a beginner's guide. San Francisco, Calif: No Starch Press, 2011. Print.
• Michaelson, Greg. An introduction to functional programming through Lambda calculus. Mineola, N.Y: Dover Publications, 2011. Print.
Websites
• Wlaschin, Scoot. F# for Fun and Profit. Web. 16 May 2016. <https://fsharpforfunandprofit.com/>.
• Seemann, Mark. ploeh blog. Web. 16 May 2016. < http://blog.ploeh.dk/ >.
Papers
• Emir, Burak, Odersky, Martin and Williams, John. Matching Objects With Patterns. LAMP-REPORT-2006-006.
• Hutton, Graham. A tutorial on the universality and expressiveness of fold. J. Functional Programming, 9 (4): 355–372, July 1999.
• Petricek, Tomas and Syme, Don. The F# Computation Expression Zoo. Proceedings of Practical Aspects of Declarative Languages, PADL 2014. San Diego, CA, USA.
• Wadler, Philip. Views︎: A way for pattern matching to cohabit with data abstraction. March ︎︎︎︎1987.