packages feed

map-reduce-folds-0.1.0.0: examples/ListStats.hs

module Main where

import qualified Control.MapReduce.Simple      as MR
import qualified Control.Foldl                 as FL

ints n = take n [1 ..]

multipleOf n x = (x `mod` n) == 0

onlyEven = MR.filterUnpack even -- a filter

andTwice x = [x, 2 * x]  -- a "melt"

withTwice :: MR.Unpack Int Int
withTwice = MR.Unpack andTwice

groupByMultOf3 = MR.assign (multipleOf 3) realToFrac

-- An example using the function version
addAll :: (Foldable f, Num a) => f a -> a
addAll = FL.fold FL.sum


reduceSum = MR.foldAndLabel FL.sum ((,))
reduceSum' = MR.processAndLabel addAll (,)
reduceMean = MR.foldAndLabel FL.mean ((,))

-- sum of all even ints, grouped by whether or not they are mutliples of 3
sumsF = MR.mapReduceFold onlyEven groupByMultOf3 reduceSum
sumsF' = MR.mapReduceFold onlyEven groupByMultOf3 reduceSum'

-- mean of all even ints, grouped by whether or not they are mutliples of 3
meansF = MR.mapReduceFold onlyEven groupByMultOf3 reduceMean

-- loop over initial list once but group each time
sumsAndMeansF = (,) <$> sumsF <*> meansF

-- loop over initial list once and group only once.
sumAndMeanEachF =
  MR.mapReduceFold onlyEven groupByMultOf3 ((,) <$> reduceSum <*> reduceMean)

-- sum and mean of all ints--and twice each int--grouped by whether or not they are multiples of 3.
sumAndMeanWithTwiceF =
  MR.mapReduceFold withTwice groupByMultOf3 ((,) <$> reduceSum <*> reduceMean)


{-
We combine all the folds we want to do into one fold.  So we loop over the input list only once here.
We group it for each fold.  But the last two, sumAndMeanEach and sumAndMeanWithTwice shows how we can avoid that as well.
-}

main :: IO ()
main = do
  let (s, s', m, sm, sme, smd) = MR.fold
        (   (,,,,,)
        <$> sumsF
        <*> sumsF'
        <*> meansF
        <*> sumsAndMeansF
        <*> sumAndMeanEachF
        <*> sumAndMeanWithTwiceF
        )
        (ints 100)
  putStrLn $ "Sums: " ++ show s
  putStrLn $ "Sums': " ++ show s'
  putStrLn $ "Means: " ++ show m
  putStrLn $ "Sums & Means: " ++ show sm
  putStrLn $ "Sum & Mean of each: " ++ show sme
  putStrLn $ "Sum & Mean of all plus doubles: " ++ show smd


{- Output:

Sums: [(False,1734.0),(True,816.0)]
Sums': [(False,1734.0),(True,816.0)]
Means: [(False,51.0),(True,51.0)]
Sums & Means: ([(False,1734.0),(True,816.0)],[(False,51.0),(True,51.0)])
Sum & Mean of each: [((False,1734.0),(False,51.0)),((True,816.0),(True,51.0))]
Sum & Mean of all plus doubles: [((False,10101.0),(False,75.38059701492539)),((True,5049.0),(True,76.5))]

-}