Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Beginning Haskell, Dive In, Its Not That Scary!

Haskell can get a bit of a reputation for being this lofty, academic, difficult to learn language. This talk aims to dispel this myth and offer an introduction to this beautiful and pragmatic language. From the point of view of someone who has been functional programming in Scala and Clojure for a while now, but who has, more recently been taking a dive into Haskell, this talk will give a basic introduction to Haskell. Hopefully it will encourage anyone who hasn't tried functional programming in Haskell to dive in too and give it a go.
The talk will be a whistle stop tour of some functional programming fundamentals in Haskell from basic data structures, logic constructs, functional transformations, recursion to some of the basics of Haskell's type system with data declarations and type classes.

  • Login to see the comments

Beginning Haskell, Dive In, Its Not That Scary!

  1. 1. Beginning Haskell Tom Prior @priortd www.prigrammer.com Newsweaver
  2. 2. Quick Search on Quora
  3. 3. Explanation? • I can’t just print hello world! • Its purity means things can often be explained in relation to maths • Use of whitespace and annoying compilation errors from it • Strict type system and purity means that programmers forced to stick to a purely functional style
  4. 4. Sounds a bit complicated ! MATHS MONADS FUNCTORS APPLICATIVES
  5. 5. I just want to print Hello World ! public class HelloWorld {
 
 public static void main (String [] args) { 
 System.out.println("Hello World");
 } 
 } 
 module HelloWorld where
 
 main :: IO()
 main = putStrLn("Hello World")
  6. 6. REPL Playground! ➜ ~ ghci GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /Users/tom/.ghci ghci> print "Hello World" "Hello World" ghci> 1 + 1 2 ghci> "Haskell " ++ "is cool" "Haskell is cool" ghci> sum [1, 2, 3] 6 ghci> :l HelloWorld.hs [1 of 1] Compiling HelloWorld ( Helloworld.hs, interpreted ) Ok, modules loaded: HelloWorld. ghci> main Hello World ghci>
  7. 7. Katas Up and Running in No Time With basic loops and logic
  8. 8. The Infamous Palindrome h u z z a h u z z a
  9. 9. h u z z u h u z z u z z
  10. 10. Imperative Java Solution public static boolean isPalindrome(String str) {
 
 int strEndIndex = str.length() - 1;
 
 for(int i = strEndIndex; i > (strEndIndex/2); i--)
 if(str.charAt(i) != str.charAt(strEndIndex - i))
 return false;
 
 return true;
 }
  11. 11. Haskell Palindrome Logic and Recursion isPalindrome :: String -> Bool
 isPalindrome str =
 loop strEndIndex where
 
 strEndIndex = length str - 1
 loop i =
 if i <= (div strEndIndex 2) then True
 else if (str !! i) /= str !! (strEndIndex - i) then False
 else loop (i - 1) DISCLAIMER: Not the Nicest Haskell Code, but gets us started !
  12. 12. Guards isPalindrome :: String -> Bool
 isPalindrome str =
 loop strEndIndex where
 
 strEndIndex = length str - 1
 loop i
 | i <= (div strEndIndex 2) = True
 | (str !! i) /= str !! (strEndIndex - i) = False
 | otherwise = loop (i - 1)
  13. 13. Refining the Palindrome Pattern Matching and Recursion isPalindrome :: String -> Bool
 isPalindrome str =
 case str of
 [] -> True
 x : [] -> True
 x1 : x2 : [] -> x1 == x2
 x1 : xs -> x1 == last xs && isPalindrome (init xs)
  14. 14. Refining the Palindrome Pattern matching without case isPalindrome :: String -> Bool
 isPalindrome [] = True
 isPalindrome (x : []) = True
 isPalindrome (x1 : x2 : []) = x1 == x2
 isPalindrome (x1 : xs) = x1 == last xs && isPalindrome (init xs)
  15. 15. List Type and Pattern Match ghci> :info [] data [] a = [] | a : [a] -- Defined in ‘GHC.Types’ ghci> 1 : 2 : 3 : [] [1,2,3] ghci> [1,2,3] [1,2,3] 1 2 3 []
  16. 16. Refining the Palindrome Is whatever a palindrome? isPalindrome :: (Eq a) => [a] -> Bool
 isPalindrome [] = True
 isPalindrome (x : []) = True
 isPalindrome (x1 : x2 : []) = x1 == x2
 isPalindrome (x1 : xs) = x1 == last xs && isPalindrome (init xs) ghci> isPalindrome [1,2,3] False ghci> isPalindrome [1,2,1] True
  17. 17. Why the (Eq a) => ? Type Classes ghci> :info Eq class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool
  18. 18. ghci> :l HaskellPlayground.hs [1 of 1] Compiling HaskellPlayground ( HaskellPlayground.hs, interpreted ) HaskellPlayground.hs:35:31: error: • No instance for (Eq a) arising from a use of ‘==’ Possible fix: add (Eq a) to the context of the type signature for: isPalindrome :: [a] -> Bool isPalindrome :: [a] -> Bool isPalindrome :: (Eq a) => [a] -> Bool
 isPalindrome [] = True
 isPalindrome (x : []) = True
 isPalindrome (x1 : x2 : []) = x1 == x2
 isPalindrome (x1 : xs) = x1 == last xs && isPalindrome (init xs)
  19. 19. I want to call isPalindrome on my own Type data Book =
 Single String
 | Trilogy String
 | Series String
 deriving (Show) data Book =
 Single { title :: String }
 | Trilogy { title :: String }
 | Series { title :: String }
 deriving (Show) ghci> let b = Trilogy {title = "Lord of the Rings"} ghci> b Trilogy {title = "Lord of the Rings”} ghci> title b "Lord of the Rings" ghci> let b2 = b {title = "Lord of the Rings Version 2"} ghci> b2 Trilogy {title = "Lord of the Rings Version 2"} ghci> b Trilogy {title = "Lord of the Rings"}
  20. 20. Is my book list a palindrome? ghci> isPalindrome [(Single "The Hobbit"), (Trilogy "Lord of the Rings"), (Single "The Hobbit")] <interactive>:22:1: error: • No instance for (Eq Book) arising from a use of ‘isPalindrome’
  21. 21. Comparing my books instance Eq Book where
 (==) (Single t1) (Single t2) = t1 == t2
 (==) (Trilogy t1) (Trilogy t2) = t1 == t2
 (==) (Series t1) (Series t2) = t1 == t2
 (==) _ _ = False ghci> :info Eq class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool
  22. 22. ghci> isPalindrome [(Single "The Hobbit"), (Trilogy "Lord of the Rings"), (Single "The Hobbit")] True ghci> isPalindrome [(Single "The Hobbit"), (Trilogy "Lord of the Rings"), (Series "The Hobbit")] False Now are my books a palindrome?
  23. 23. Derving Type Classes data Book =
 Single String
 | Trilogy String
 | Series String
 deriving (Show, Eq) ghci> :info Show class Show a where …. show :: a -> String ….
  24. 24. Are they all palindromes? ["racecar","wow","huzzah"] allPalindromes = areAllPalindromes [
 [(Single "S"), (Trilogy "T"), (Single "S")],
 [(Series "S"), (Trilogy "T"), (Series "S")]
 ] allPalindromes = areAllPalindromes [
 [(Single "S"), (Trilogy "T"), (Single "S")],
 [(Series "S"), (Trilogy "T"), (Series "S2")]
 ]
  25. 25. Are they all palindromes? Almost imperative style loop areAllPalindromes :: (Eq a) => [[a]] -> Bool
 areAllPalindromes listOfLists =
 loop listOfLists where
 loop lOfl =
 case lOfl of
 [] -> True
 (x : xs) -> isPalindrome x && loop xs ghci> areAllPalindromes ["racecar", "wow", "huzzuh"] True ghci> areAllPalindromes ["racecar", "wow", "huzzah"] False
  26. 26. Are they all palindromes? Refining the recursion areAllPalindromes :: (Eq a) => [[a]] -> Bool
 areAllPalindromes [] = True
 areAllPalindromes (x : xs) = isPalindrome x && areAllPalindromes xs
  27. 27. Are they all palindromes? FoldareAllPalindromes :: (Eq a) => [[a]] -> Bool
 areAllPalindromes lOfLs =
 foldr (x result -> isPalindrome x && result) True lOfLs ["racecar", "wow", "huzzah"] reduces as follows: (isPalindrome "racecar") True && ((isPalindrome "wow") True && ((isPalindrome “huzzah") False && True)))
  28. 28. Point Free Niceness ! palindromeWithAnding :: (Eq a) => [a] -> Bool -> Bool
 palindromeWithAnding x b = (&&) (isPalindrome x) b ghci> palindromeWithAnding "huzzuh" False False ghci> palindromeWithAnding "huzzuh" True True Function by Name Binding.. areAllPalindromes :: (Eq a) => [[a]] -> Bool
 areAllPalindromes lOfLs = foldr palindromeWithAnding True lOfLs
  29. 29. Map and then Fold ghci> map isPalindrome ["racecar", "wow", “huzzah"] [True,True,False] areAllPalindromes :: (Eq a) => [[a]] -> Bool
 areAllPalindromes lOfLs = foldr (x result -> x && result) True (map isPalindrome lOfLs) WITH POINT FREE && areAllPalindromes :: (Eq a) => [[a]] -> Bool
 areAllPalindromes lOfLs = foldr (&&) True (map isPalindrome lOfLs)
  30. 30. Automatic Currying Niceness !map isPalindrome lOfLs ghci> :t map map :: (a -> b) -> [a] -> [b] So.. map func list pseudocode map = func -> list -> ‘map this list with func function’ map isPalindrome list -> ‘map this list with isPalindrome function’
  31. 31. areAllPalindromes lOfLs = (foldr (&&) True) (map isPalindrome lOfLs) map and then fold fold . map areAllPalindromes lOfLs = (foldr (&&) True) . (map isPalindrome) $ lOfLs areAllPalindromes = (foldr (&&) True) . (map isPalindrome) areAllPalindromes = foldr (&&) True . map isPalindrome Function Composition Niceness !
  32. 32. Composition and Point Free Pipeline Declaration Focusing on Transformations Map with isPalindrome Fold with && ["racecar", "wow", "huzzuh"] [True, True, True] True
  33. 33. onlyPalindromes :: (Eq a) => [[a]] -> [[a]]
 onlyPalindromes xs = filter isPalindrome xs ghci> onlyPalindromes ["racecar", "huzzah", "wow"] [“racecar","wow"] USING AUTOMATIC CURRYING onlyPalindromes :: (Eq a) => [[a]] -> [[a]]
 onlyPalindromes = filter isPalindrome Filter Palindromes
  34. 34. Haskell Laziness ghci> length ["racecar", "huzzah", undefined] 3 ghci> length (map head ["racecar", "huzzah", undefined]) 3 ghci> take 2 (map head ["racecar", "huzzah", undefined]) “rh" ghci> take 3 (map head ["racecar", "huzzah", undefined]) "rh*** Exception: Prelude.undefined ghci> take 1 (filter isPalindrome ["racecar", "huzzah", undefined]) [“racecar"] ghci> take 2 (filter isPalindrome ["racecar", "huzzah", undefined]) ["racecar"*** Exception: Prelude.undefined
  35. 35. How do I get started https://www.haskell.org/platform/ Start a REPL with ➜ ~ ghci GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /Users/tom/.ghci ghci> Play with the examples from this talk GitHub priort
  36. 36. Books haskellbook.com

×