packages feed

liquidhaskell-0.4.0.0: tests/pos/mapreduce-bare.hs

module Meas () where

import Language.Haskell.Liquid.Prelude
import Data.List (foldl')

----------------------------------------------------------------
--- Step 1: Map each element into key-value list (concatMap) ---
----------------------------------------------------------------

expand          :: (a -> [(k,v)]) -> [a] -> [(k, v)]
expand f []     = []
expand f (x:xs) = (f x) ++ (expand f xs)

----------------------------------------------------------------
--- Step 2: Group By Key ---------------------------------------
----------------------------------------------------------------

group ::[(Int, v)] -> [(Int, [v])]
group = foldl' addKV [] 
  
addKV m (k, v) = insert k vs' m
  where vs' = v : (findWithDefault [] k m)

insert key value [] 
  = [(key, value)]
insert key value ((k,_):kvs)
  | k == key
  = (key, value):kvs
insert key value (kv:kvs)
  = kv : insert key value kvs  

{-@ Decrease findWithDefault 3 @-}
findWithDefault r _ ([]) 
  = r
findWithDefault r k ((key,value):_) 
  | k `eq` key 
  = value
findWithDefault r k (_:kvs) 
  = findWithDefault r k kvs 

----------------------------------------------------------------
--- Step 3: Group By Key ---------------------------------------
----------------------------------------------------------------

collapse f = foldrWithKey reduceKV []
  where reduceKV k (v:vs) acc = (k, foldl' f v vs) : acc
        reduceKV k []     _   = crash False -- error $ show (liquidAssertB False)

foldrWithKey f = foldr (\(k, v) acc -> f k v acc) 

----------------------------------------------------------------
--- Putting it All Together ------------------------------------
----------------------------------------------------------------

mapReduce fmap fred xs = collapse fred $ group $ expand fmap xs

----------------------------------------------------------------
--- "Word Count" -----------------------------------------------
----------------------------------------------------------------

wordCount  = mapReduce fm plus 
  where fm = \doc -> [ (length w, 1) | w <- words doc]

mytest = 
  let docs = [ "this is the end"
             , "go to the end"
             , "the end is the beginning"]
  in putStrLn $ isZero {- show -} $ wordCount docs
 
isZero [_]  = "Positive" 
isZero _    = "Negative"