Contact/support | Changelog

http://stackoverflow.com/questions/10803221/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
-- http://stackoverflow.com/questions/10803221/haskell-can-i-perform-several-folds-over-the-same-lazy-list-without-keeping-lis
{-# LANGUAGE GADTs, BangPatterns #-}

import Data.List (foldl', unfoldr)
import Control.Applicative 
import qualified Data.ByteString.Lazy.Char8 as B
import qualified Data.Vector.Unboxed as V

main = fmap readIntsV (B.readFile "ints.txt") >>= print . foldV allThree
  where allThree = Three <$> length_ <*> sum_ <*> maximum_

data Three = Three {-#UNPACK#-} !Int  {-#UNPACK#-} !Int {-#UNPACK#-} !Int deriving Show

data Fold b c where  F ::  (a -> b -> a) -> !a -> (a -> c) -> Fold b c

data Pair a b = P !a !b

instance Functor (Fold b) where  fmap f (F op x g) = F op x (f . g)

instance Applicative (Fold b) where
  pure !c = F const () (const c)
  (F f x c) <*> (F g y c') = F (comb f g) (P x y) (c *** c')
    where comb f g (P a a') !b = P (f a b) (g a' b)
          (***) f g (P x y) = f x ( g y)

fold :: Fold b c -> [b] -> c
fold (F f x c) bs = c $ (foldl' f x bs)

foldV :: V.Unbox b => Fold b c -> V.Vector b -> c
foldV (F f x c) bs = c $ (V.foldl' f x bs)

sum_, product_ :: Num a => Fold a a
sum_ = F (+) 0 id
product_ = F (*) 1 id

length_ :: Fold a Int
length_ = F (const . (+1)) 0 id
maximum_ = F max 0 id

readInts  = unfoldr $ \bs0 -> case B.readInt bs0 of
      Nothing      -> Nothing
      Just (n,bs2) -> case B.uncons bs2 of 
                        Just (_, bs3) -> Just (n,bs3)
                        Nothing       -> Just (n,B.empty)
                        
readIntsV  = V.unfoldr $ \bs0 -> case B.readInt bs0 of
      Nothing      -> Nothing
      Just (n,bs2) -> case B.uncons bs2 of 
                        Just (_, bs3) -> Just (n,bs3)
                        Nothing       -> Just (n,B.empty)