Pursuing the Strong, Not So Silent Type: A Haskell Story

665 views

Published on

In recent months Katie's Facebook team has completely replaced an in-house interpreted language, moving to a strong and statically typed Haskell DSL called Haxl. Dozens of Facebook developers have become functional programmers, using the open-source Haxl framework to battle spam at scale. This talk will explain how Haskell shines in this context, bust a few myths about the language, and highlight lessons Rubyists and Haskellers could learn from each other.

Published in: Software
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
665
On SlideShare
0
From Embeds
0
Number of Embeds
10
Actions
Shares
0
Downloads
9
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Pursuing the Strong, Not So Silent Type: A Haskell Story

  1. 1. Pursuing the strong, not so silent type A Haskell story by Katie Miller (@codemiller) Software Engineer at Facebook
  2. 2. "The limits of my language mean the limits of my world" - Ludwig Wittgenstein
  3. 3. strong static types
  4. 4. Source: Ruin Raider on Flickr, CC BY-NC-ND 2.0
  5. 5. more than 1 million requests/second
  6. 6. def  haskell_spammer(user,  friend,  post)      if  talking_about_haskell(post)  &&                num_common_friends(user,  friend)  <  5  &&                most_friends_like_ruby(friend)          block_post      else          do_nothing      end   end  
  7. 7. continuous deployment
  8. 8. FXL
  9. 9. functional
  10. 10. efficient data fetching
  11. 11. automatic batching and concurrency
  12. 12. HaskellSpammer  =      If  (TalkingAboutHaskell(postContent)  &&              NumCommonFriends(userId,  friendId)  <  5  &&              MostFriendsLikeRuby(friendId))          Then  BlockAction  Else  @[]   NumCommonFriends(x,  y)  =      Length(Intersect(FriendsOf(x),  FriendsOf(y)))  
  13. 13. 20x speedup
  14. 14. Haskell
  15. 15. Is Haskell academic?
  16. 16. Source: https://xkcd.com/1312
  17. 17. reasoning about code
  18. 18. haskellSpammer  ::  Haxl  Bool   haskellSpammer  =        talkingAboutHaskell  .&&      numCommonFriends  .<  5  .&&      mostFriendsLikeRuby      where      mostFriendsLikeRuby  =  do          friends  <-­‐  getFriends          rubyFriends  <-­‐  filterM  friendLikesRuby  friends          return  (length  rubyFriends  >=              length  friends  `div`  2)      friendLikesRuby  friend  =          hasAssoc  friend  likeAssoc  rubyPage
  19. 19. user-defined data types
  20. 20. hasAssoc  ::  Int  -­‐>  Int  -­‐>  Int  -­‐>  Bool   hasAssoc  id  assoc  target  =  ...
  21. 21. hasAssoc  ::  Int  -­‐>  Int  -­‐>  Int  -­‐>  Bool   hasAssoc  id  assoc  target  =  ... newtype  Id  =  Id  Int   newtype  AssocId  =  AssocId  Int
  22. 22. hasAssoc  ::  Int  -­‐>  Int  -­‐>  Int  -­‐>  Bool   hasAssoc  id  assoc  target  =  ... newtype  Id  =  Id  Int   newtype  AssocId  =  AssocId  Int hasAssoc  ::  Id  -­‐>  AssocId  -­‐>  Id  -­‐>  Bool   hasAssoc  id  assoc  target  =  ...
  23. 23. data  Language  =  Ruby  |  Haskell  |  Php
  24. 24. data  Language  =  Ruby  |  Haskell  |  Php likesLanguage  ::  Language  -­‐>  Id  -­‐>  Bool
  25. 25. data  Language  =  Ruby  |  Haskell  |  Php likesLanguage  ::  Language  -­‐>  Id  -­‐>  Bool likesLanguage  Ruby  userId  =      hasAssoc  userId  likesAssoc  1995  ||      hasAssoc  userId  likesAssoc  2005
  26. 26. data  Language  =  Ruby  |  Haskell  |  Php likesLanguage  ::  Language  -­‐>  Id  -­‐>  Bool likesLanguage  Ruby  userId  =      hasAssoc  userId  likesAssoc  1995  ||      hasAssoc  userId  likesAssoc  2005 likesLanguage  Haskell  userId  =      hasAssoc  userId  likesAssoc  42
  27. 27. data  Language  =  Ruby  |  Haskell  |  Php likesLanguage  ::  Language  -­‐>  Id  -­‐>  Bool likesLanguage  Ruby  userId  =      hasAssoc  userId  likesAssoc  1995  ||      hasAssoc  userId  likesAssoc  2005 likesLanguage  Haskell  userId  =      hasAssoc  userId  likesAssoc  42 likesLanguage  Php  _  =      False
  28. 28. Is Haskell difficult to learn?
  29. 29. expectations
  30. 30. Is Haskell a panacea?
  31. 31. blockAustralians  ::  Haxl  SyncResponses   blockAustralians  =  do      textMap  <-­‐  textArr      let  text  =  HashMap.lookupDefault  ""  "main_text"  textMap              numBadWords      =  length  $  filter  (`Text.isInfixOf`  text)  aussieTerms              numBadPhrases  =  length  $  filter  (`Text.isInfixOf`  text)  aussieSayings      if  numBadWords  <  2  &&  numBadPhrases  <=  0      then  return  noResponses      else              if  numBadWords  <  4  &&  numBadPhrases  <  2              then  return  requireCaptcha              else                      if  numBadWords  <  5  &&  numBadPhrases  <  3                      then  return  $  responses  [warnUser,  requireCaptcha]                      else                              if  numBadWords  <  7  &&  numBadPhrases  <  4                              then  return  warnUser                              else                                      if  numBadWords  <  8  &&  numBadPhrases  <  5                                      then  return  $  responses  [warnUser,  blockAccess]                                      else                                              if  numBadWords  <  10  &&  numBadPhrases  <  6                                              then  return  blockAccess                                              else                                                      if  numBadWords  <  13  &&  numBadPhrases  <  7                                                      then  return  $  responses                                                                        [  blockAccess                                                                        ,  enrollInFakeAccountCheckpoint                                                                        ]                                                      else  return  $  responses                                                                        [  blockAccess                                                                        ,  enrollInFakeAccountCheckpoint                                                                        ,  requireCaptcha                                                                        ]          where              aussieTerms  =                      [  "Acca  Dacca"                      ,  "ambo"                      ,  "arvo"                      ,  "Aussie"                      ,  "bangaroo"
  32. 32. blockAustralians  ::  Haxl  SyncResponses   blockAustralians  =  do      textMap  <-­‐  textArr      let  text  =  HashMap.lookupDefault  ""  "main_text"  textMap              numBadWords      =  length  $  filter  (`Text.isInfixOf`  text)  aussieTerms              numBadPhrases  =  length  $  filter  (`Text.isInfixOf`  text)  aussieSayings      if  numBadWords  <  2  &&  numBadPhrases  <=  0      then  return  noResponses      else              if  numBadWords  <  4  &&  numBadPhrases  <  2              then  return  requireCaptcha              else                      if  numBadWords  <  5  &&  numBadPhrases  <  3                      then  return  $  responses  [warnUser,  requireCaptcha]                      else                              if  numBadWords  <  7  &&  numBadPhrases  <  4                              then  return  warnUser                              else                                      if  numBadWords  <  8  &&  numBadPhrases  <  5                                      then  return  $  responses  [warnUser,  blockAccess]                                      else                                              if  numBadWords  <  10  &&  numBadPhrases  <  6                                              then  return  blockAccess                                              else                                                      if  numBadWords  <  13  &&  numBadPhrases  <  7                                                      then  return  $  responses                                                                        [  blockAccess                                                                        ,  enrollInFakeAccountCheckpoint                                                                        ]                                                      else  return  $  responses                                                                        [  blockAccess                                                                        ,  enrollInFakeAccountCheckpoint                                                                        ,  requireCaptcha                                                                        ]          where              aussieTerms  =                      [  "Acca  Dacca"                      ,  "ambo"                      ,  "arvo"                      ,  "Aussie"                      ,  "bangaroo"
  33. 33. results
  34. 34. ideas worth pursuing
  35. 35. community
  36. 36. Haxl team past and present Louis Brandy Jonathan Coens Andrew Farmer Kubo Kováč Jake Lengyel Simon Marlow Katie Miller Bartosz Nitka Jon Purdy Aaron Roth Zejun Wu Noam Zilberstein
  37. 37. More about Haxl Haxl on GitHub 'Fighting spam with Haskell' blog post 'There is no Fork' ICFP paper and presentation 'The Road to Running Haskell at Facebook Scale' presentation Wired article
  38. 38. The End by Katie Miller (@codemiller) Software Engineer at Facebook

×