packages feed

storablevector-0.2.12: tests/Alternative/Lazy.hs

{- |
Alternative implementations for functions in "Data.StorableVector.Lazy".
We want to use it for testing against the prefered implementations.
-}
module Alternative.Lazy where

import qualified Data.List.Match as Match
import qualified Data.List as List
import Data.Tuple.HT (mapFst)
import Data.Maybe.HT (toMaybe)


-- compact0 2 [] = [[]] - bad
-- compact0 2 [10] = [[],[10]] - bad
compact0 :: Int -> [Int] -> [[Int]]
compact0 maxS =
   let go _ xs [] = [xs]
       go s0 xs (y:ys) =
         let s1 = s0+y
         in  if s1<=maxS
               then go s1 (xs++[y]) ys
               else xs : go y [y] ys
   in  go 0 []

-- compact1 2 [] = [[]] - bad
-- compact1 2 [10] = [[],[10]] - bad
compact1 :: Int -> [Int] -> [[Int]]
compact1 maxS =
   let go _ [] = ([], [])
       go s0 (y:ys) =
         let s1 = s0+y
         in  if s1<=maxS
               then mapFst (y:) $ go s1 ys
               else ([], uncurry (:) $ mapFst (y:) $ go y ys)
   in  uncurry (:) . go 0

compact2 :: Int -> [Int] -> [[Int]]
compact2 maxS =
   let go _ [] = ([], [])
       go s0 (y:ys) =
         let s1 = s0+y
         in  if s1<=maxS
               then mapFst (y:) $ go s1 ys
               else ([], uncurry (:) $ mapFst (y:) $ go y ys)
   in  (\(xs,xss) -> if List.null xs then xss else xs:xss) . go 0

{- |
This is the counterpart to the actual implementation in StorableVector.Lazy.
-}
compact3 :: Int -> [Int] -> [[Int]]
compact3 maxS =
   (\(xs,xss) -> if List.null xs then xss else xs:xss) .
   (\xs ->
      List.foldr
         (\y go s0 ->
            let s1 = s0+y
            in  if s1<=maxS
                  then mapFst (y:) $ go s1
                  else ([], uncurry (:) $ mapFst (y:) $ go y))
         (const ([], [])) xs 0)

compact4 :: Int -> [Int] -> [[Int]]
compact4 maxS =
   List.unfoldr $ \xs -> toMaybe (not $ List.null xs) $
      Match.splitAt
         (minLength1 $ List.takeWhile (<= maxS) $
          List.tail $ List.scanl (+) 0 xs)
         xs

minLength1 :: [Int] -> [Int]
minLength1 = (0:) . List.drop 1