Upcoming SlideShare
×

FizzBuzz in Haskell by Embedding a DSL

955 views

Published on

Fun in the Afternoon @ Facebook (March 2014)

Published in: Technology
0 Likes
Statistics
Notes
• Full Name
Comment goes here.

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

• Be the first to like this

Views
Total views
955
On SlideShare
0
From Embeds
0
Number of Embeds
30
Actions
Shares
0
2
0
Likes
0
Embeds 0
No embeds

No notes for slide

FizzBuzz in Haskell by Embedding a DSL

1. 1. FizzBuzz in Haskell by Embedding a DSL or: how to get a job (at Facebook?) Maciej Piróg UOxford FUN@FB March 2014
2. 2. Players generally sit  in a circle. The player  designated to go first says the number "1",  and each player thenceforth counts one number  in turn. However, any number divisible by  three is replaced by the word fizz and any  divisible by five by the word buzz. Numbers  divisible by both become fizzbuzz.                                   [Wikipedia] FizzBuzz ­­ a simple game for children
3. 3. FizzBuzz ­­ a hard nut to crack for programmers fizzbuzz n = “fizzbuzz” if    n`mod`3==0               && n`mod`5==0 “fizz”     if n`mod`3==0  “buzz”     if n`mod`5==0 show n     otherwise
4. 4. FizzBuzz ­­ a hard nut to crack for programmers fizzbuzz n = “fizzbuzz” if    n`mod`3==0               && n`mod`5==0 “fizz”     if n`mod`3==0  “buzz”     if n`mod`5==0 show n     otherwise What about FizzBuzzHissHowl problem for mod3, mod5, mod7, and mod11? We repeat e.g. mod3 test (modularity?)
5. 5. fizzbuzz n :: Int ­> String fizzbuzz n =   if n `mod` 3 == 0     then "fizz" ++  if n `mod` 5 == 0                       then "buzz"                       else ""     else  if n `mod` 5 == 0                       then "buzz"                       else show n  Solution B
6. 6. (+<+) :: String ­> String ­> String "" +<+ s = s a  +<+ s = a fizzbuzz :: Int ­> String fizzbuzz n =  (  (if n`mod`3==0 then "fizz" else "")  ++ (if n`mod`5==0 then "buzz" else "") )  +<+ show n  Solution C
7. 7. data Cmd      = Print String | Skip | Halt  type Program  = [Cmd] interp :: Program ­> String interp []             = "" interp (Print s : xs) = s ++ interp xs interp (Skip    : xs) = interp xs interp (Halt    : xs) = ""  The Skip­Halt­Print  language
8. 8. [Skip, Halt, Print "fun"] One­hole contexts [Skip, Halt, ? , Print "fun"] [Skip, Halt] ++ ? ++ [Print "fun"] x   [Skip, Halt] ++ → x ++ [Print "fun"] type Cont = Program ­> Program Higher-order abstract syntax
9. 9. base, fizz, buzz :: Int ­> Cont base  n       = x   → x ++ [Print (show n)] fizz  n  | n`mod`3==0 = x   [Print "fizz"] ++ → x ++ [Halt]  | otherwise  = id buzz  n  | n`mod`5==0 = x   [Print "buzz"] ++ → x ++ [Halt]  | otherwise  = id fb :: Int ­> Program fb n = (base n . fizz n . buzz n) [Skip] fizzbuzz :: Int ­> String fizzbuzz n = interp (fb n)
10. 10. Spin the wheel step :: Cmd ­> String ­> String step Skip       t  = t step Halt       t  = "" step (Print s)  t  = s ++ t interp = foldr step "" interp is a fold!
11. 11. Spin the wheel (2) foldr step "" [Print "c", Halt, Skip] = foldr (.) id [step (Print "c"), step Halt,               step Skip]  "" Since foldr step "" p = foldr (.) id (fmap step p) ""
12. 12. Spin the wheel (2) foldr step "" [Print "c", Halt, Skip] = foldr (.) id [step (Print "c"), step Halt,               step Skip]  "" = foldr (.) id [("c"++), const "", id] "" inlining
13. 13. Spin the wheel (2) foldr step "" [Print "c", Halt, Skip] = foldr (.) id [step (Print "c"), step Halt,               step Skip]  "" = foldr (.) id [("c"++), const "", id] "" = (("c"++) . (const "") . id) "" more inlining
14. 14. base, fizz, buzz :: Int ­> Cont base  n       = x   → x ++ [Print (show n)] fizz  n  | n`mod`3==0 = x   [Print "fizz"] ++ → x ++ [Halt]  | otherwise  = id buzz  n  | n`mod`5==0 = x   [Print "buzz"] ++ → x ++ [Halt]  | otherwise  = id fb :: Int ­> Program fb n = (base n . fizz n . buzz n) [Skip] fizzbuzz :: Int ­> String fizzbuzz n = interp (fb n)
15. 15. base, fizz, buzz :: Int ­> Cont base  n       = x   → x . (show n ++) fizz  n  | n`mod`3==0 = x   ("fizz" ++) . → x . (const "")  | otherwise  = id buzz  n  | n`mod`5==0 = x   ("buzz" ++) . → x . (const "")  | otherwise  = id fizzbuzz :: Int ­> String fizzbuzz n = (base n . fizz n . buzz n) ""
16. 16. fizzbuzz :: Int ­> String fizzbuzz n = (fizz . buzz) id (show n)  where   fizz  n    | n`mod`3==0 = x   const ("fizz" ++ → x "")    | otherwise  = id   buzz  n    | n`mod`5==0 = x   const ("buzz" ++ → x "")    | otherwise  = id
17. 17. fizzbuzz :: Int ­> String fizzbuzz n =   (test 3 "fizz" . test 5  "buzz") id (show n)  where   test d s x    | n`mod`d==0 =  const  (s ++ x "")    | otherwise  =  x     test ::   Int­>String­>(String­>String)­>String­>String
18. 18. The End Questions?