![Page 1: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/1.jpg)
Pursuing the strong, not so silent type
A Haskell story
by Katie Miller (@codemiller) Software Engineer at Facebook
![Page 2: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/2.jpg)
![Page 3: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/3.jpg)
"The limits of my language mean the limits of my world"
- Ludwig Wittgenstein
![Page 4: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/4.jpg)
strong static types
![Page 5: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/5.jpg)
Source: Ruin Raider on Flickr, CC BY-NC-ND 2.0
![Page 6: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/6.jpg)
![Page 7: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/7.jpg)
![Page 8: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/8.jpg)
![Page 9: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/9.jpg)
![Page 10: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/10.jpg)
![Page 11: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/11.jpg)
more than 1 million requests/second
![Page 12: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/12.jpg)
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
![Page 13: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/13.jpg)
continuous deployment
![Page 14: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/14.jpg)
FXL
![Page 15: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/15.jpg)
functional
![Page 16: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/16.jpg)
efficient data fetching
![Page 17: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/17.jpg)
automatic batching and concurrency
![Page 18: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/18.jpg)
HaskellSpammer = If (TalkingAboutHaskell(postContent) && NumCommonFriends(userId, friendId) < 5 && MostFriendsLikeRuby(friendId)) Then BlockAction Else @[]
NumCommonFriends(x, y) = Length(Intersect(FriendsOf(x), FriendsOf(y)))
![Page 19: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/19.jpg)
20x speedup
![Page 20: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/20.jpg)
![Page 21: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/21.jpg)
Haskell
![Page 22: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/22.jpg)
Is Haskell academic?
![Page 24: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/24.jpg)
reasoning about code
![Page 25: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/25.jpg)
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
![Page 26: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/26.jpg)
user-defined data types
![Page 27: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/27.jpg)
hasAssoc :: Int -‐> Int -‐> Int -‐> Bool hasAssoc id assoc target = ...
![Page 28: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/28.jpg)
hasAssoc :: Int -‐> Int -‐> Int -‐> Bool hasAssoc id assoc target = ...
newtype Id = Id Int newtype AssocId = AssocId Int
![Page 29: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/29.jpg)
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 = ...
![Page 30: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/30.jpg)
data Language = Ruby | Haskell | Php
![Page 31: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/31.jpg)
data Language = Ruby | Haskell | Php
likesLanguage :: Language -‐> Id -‐> Bool
![Page 32: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/32.jpg)
data Language = Ruby | Haskell | Php
likesLanguage :: Language -‐> Id -‐> BoollikesLanguage Ruby userId = hasAssoc userId likesAssoc 1995 || hasAssoc userId likesAssoc 2005
![Page 33: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/33.jpg)
data Language = Ruby | Haskell | Php
likesLanguage :: Language -‐> Id -‐> BoollikesLanguage Ruby userId = hasAssoc userId likesAssoc 1995 || hasAssoc userId likesAssoc 2005likesLanguage Haskell userId = hasAssoc userId likesAssoc 42
![Page 34: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/34.jpg)
data Language = Ruby | Haskell | Php
likesLanguage :: Language -‐> Id -‐> BoollikesLanguage Ruby userId = hasAssoc userId likesAssoc 1995 || hasAssoc userId likesAssoc 2005likesLanguage Haskell userId = hasAssoc userId likesAssoc 42likesLanguage Php _ = False
![Page 35: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/35.jpg)
Is Haskell difficult to learn?
![Page 36: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/36.jpg)
expectations
![Page 37: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/37.jpg)
![Page 38: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/38.jpg)
Is Haskell a panacea?
![Page 39: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/39.jpg)
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"
![Page 40: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/40.jpg)
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"
![Page 41: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/41.jpg)
results
![Page 42: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/42.jpg)
ideas worth pursuing
![Page 43: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/43.jpg)
community
![Page 44: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/44.jpg)
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
![Page 45: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/45.jpg)
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
![Page 46: Pursuing the Strong, Not So Silent Type: A Haskell Story](https://reader031.vdocument.in/reader031/viewer/2022012923/589d05bf1a28ab255c8b5a91/html5/thumbnails/46.jpg)
The End
by Katie Miller (@codemiller) Software Engineer at Facebook