Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PureScript Lunch-n-Learn Lesson 4

PureScript Lunch-n-Learn Lesson 4

Slides for the fourth lesson in my PureScript lunch-n-learn series. This lesson picks up from the last on "Recursion, Maps, & Folds," covering filtering and "do" notation. The material builds upon chapter 4 of "PureScript by Example."

Jim Fitzpatrick

July 21, 2016
Tweet

More Decks by Jim Fitzpatrick

Other Decks in Programming

Transcript

  1. PureScript Lunch & Learn 4: Recursion, Maps & Folds (pt.

    2) github.com/jimf/purescript-lunchnlearn
  2. Last lesson’s “homework” Write a recursive function countEvens that takes

    an array of integers (Array Int) and returns the number of even integers in the array.
  3. Last lesson’s “homework” countEvens :: Array Int -> Int countEvens

    xs | null xs = 0 | otherwise = case uncons xs of Just { head: x, tail: xs } -> (boolToInt <<< isEven) x + countEvens xs _ -> 0
  4. • Look at filtering and do notation • Solve related

    problems in an interactive, “dojo” style Goals
  5. This lesson is built upon Ch. 4 of PureScript by

    Example. Be sure to check it out: https://leanpub.com/purescript/read#leanpub-auto-recursion-maps-and-folds Note
  6. • Apply a “truth test” function to each value of

    a collection • Return a subset of the collection where each value passes the truth test • Original collection is unmodified filter
  7. • Apply a “truth test” function to each value of

    a collection • Return a subset of the collection where each value passes the truth test • Original collection is unmodified filter
  8. • Apply a “truth test” function to each value of

    a collection • Return a subset of the collection where each value passes the truth test • Original collection is unmodified filter
  9. • Flattens a collection by 1 level ◦ An array

    of arrays becomes a single array ◦ A list of lists becomes a single list ◦ etc. concat
  10. Examples > import Prelude > import Data.Array > filter (\n

    -> n `mod` 2 == 0) (1..10) [2, 4, 6, 8, 10] > concat [[1, 2, 3], [4, 5], [6]] [1, 2, 3, 4, 5, 6] > concatMap (\n -> [n, n * n]) (1..5) [1, 1, 2, 4, 3, 9, 4, 16, 5, 25]
  11. • Lets write a factors function to find the factors

    of n • Brute force by generating all pairs from 1..n Array Comprehensions
  12. factors > let pairs n = concatMap (\i -> 1

    .. n) (1 .. n) > pairs 3 [1,2,3,1,2,3,1,2,3]
  13. factors > let pairs n = concatMap (\i -> 1

    .. n) (1 .. n) > pairs 3 [1,2,3,1,2,3,1,2,3] Not quite. We’re looking for pairs. Need to map over inner copy.
  14. factors > let pairs n = concatMap (\i -> 1

    .. n) (1 .. n) > pairs 3 [1,2,3,1,2,3,1,2,3] > let pairs' n = concatMap (\i -> map (\j -> [i, j]) (1 .. n)) (1 .. n) > pairs' 3 [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]]
  15. factors > let pairs n = concatMap (\i -> 1

    .. n) (1 .. n) > pairs 3 [1,2,3,1,2,3,1,2,3] > let pairs' n = concatMap (\i -> map (\j -> [i, j]) (1 .. n)) (1 .. n) > pairs' 3 [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]] Better, but we have duplicates (e.g., [1, 2] and [2, 1])
  16. factors > let pairs n = concatMap (\i -> 1

    .. n) (1 .. n) > pairs 3 [1,2,3,1,2,3,1,2,3] > let pairs' n = concatMap (\i -> map (\j -> [i, j]) (1 .. n)) (1 .. n) > pairs' 3 [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]] > let pairs'' n = concatMap (\i -> map (\j -> [i, j]) (i .. n)) (1 .. n) > pairs'' 3 [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]]
  17. factors > let pairs n = concatMap (\i -> 1

    .. n) (1 .. n) > pairs 3 [1,2,3,1,2,3,1,2,3] > let pairs' n = concatMap (\i -> map (\j -> [i, j]) (1 .. n)) (1 .. n) > pairs' 3 [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]] > let pairs'' n = concatMap (\i -> map (\j -> [i, j]) (i .. n)) (1 .. n) > pairs'' 3 [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]] Perfect! Lets use filter to get our result.
  18. factors > let pairs n = concatMap (\i -> 1

    .. n) (1 .. n) > pairs 3 [1,2,3,1,2,3,1,2,3] > let pairs' n = concatMap (\i -> map (\j -> [i, j]) (1 .. n)) (1 .. n) > pairs' 3 [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]] > let pairs'' n = concatMap (\i -> map (\j -> [i, j]) (i .. n)) (1 .. n) > pairs'' 3 [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]] > import Data.Foldable > let factors n = filter (\pair -> product pair == n) (pairs'' n) > factors 10 [[1,10],[2,5]]
  19. factors > let pairs n = concatMap (\i -> 1

    .. n) (1 .. n) > pairs 3 [1,2,3,1,2,3,1,2,3] > let pairs' n = concatMap (\i -> map (\j -> [i, j]) (1 .. n)) (1 .. n) > pairs' 3 [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]] > let pairs'' n = concatMap (\i -> map (\j -> [i, j]) (i .. n)) (1 .. n) > pairs'' 3 [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]] > import Data.Foldable > let factors n = filter (\pair -> product pair == n) (pairs'' n) > factors 10 [[1,10],[2,5]] Reduces a list of Ints down to their product. (e.g., product [1, 2, 3, 4] returns 24)
  20. • Powerful sugar for defining a block with a number

    of capabilities: ◦ Assign names to expressions using <- ◦ Assign names to expressions using let ◦ Leverage type inference with pure do Notation
  21. do Notation -- Factors. factors :: Int -> Array (Array

    Int) factors n = filter (\xs -> product xs == n) $ do i <- 1 .. n j <- i .. n pure [i, j]
  22. • Function that is useful within do notation • Comes

    from Control.MonadZero (purescript-control) • :type guard ◦ forall m. (MonadZero m) => Boolean -> m Unit • More general than arrays • Can be used to filter array comprehensions guard
  23. guard import Control.MonadZero (guard) -- Factors. factors :: Int ->

    Array (Array Int) factors n = do i <- 1 .. n j <- i .. n guard $ i * j == n pure [i, j]
  24. guard import Control.MonadZero (guard) -- Factors. factors :: Int ->

    Array (Array Int) factors n = do i <- 1 .. n j <- i .. n guard $ i * j == n pure [i, j] Moves the conditional inside the comprehension
  25. guard import Control.MonadZero (guard) -- Factors. factors :: Int ->

    Array (Array Int) factors n = do i <- 1 .. n j <- i .. n guard $ i * j == n pure [i, j] Moves the conditional inside the comprehension Leverages the type system to Do The Right Thing™
  26. guard import Control.MonadZero (guard) -- Factors. factors :: Int ->

    Array (Array Int) factors n = do i <- 1 .. n j <- i .. n guard $ i * j == n [[i, j]]