packages feed

binary-list 0.3.0.0 → 0.3.1.0

raw patch · 3 files changed

+101/−7 lines, 3 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Data.BinaryList: fold :: Foldable t => forall m. Monoid m => t m -> m
+ Data.BinaryList: generate :: Int -> (Int -> a) -> BinList a
+ Data.BinaryList: take :: Int -> BinList a -> BinList a
+ Data.BinaryList: takeEnd :: Int -> BinList a -> BinList a

Files

Data/BinaryList.hs view
@@ -12,7 +12,7 @@ --   It is impossible for the user of this library to create a binary list --   whose length is /not/ a power of two. -----   Since many names in this module crashes with the names of some "Prelude"+--   Since many names in this module clash with the names of some "Prelude" --   functions, you probably want to import this module this way: -- -- > import Data.BinaryList (BinList)@@ -22,6 +22,14 @@ --   classes. If you are missing a function here, look for functions using those --   instances. --+--   Note that some functions like 'replicate', 'generate', or 'take', don't use+--   the length of the list as argument, but the exponent of its length expressed+--   as a power of two. Throughout this document, this is referred (perhaps improperly)+--   as the /length index/. For example, if the list has length 16, its length index+--   is 4 since 2^4 = 16. Therefore @replicate 4 0@ will create a list with 16 zeroes.+--   Keep this in mind when using this library. Note as well that this implies that+--   there is no need to check that the length argument is or is not a power of two.+-- module Data.BinaryList (     -- * Type     BinList@@ -31,15 +39,17 @@   , replicate   , replicateA   , replicateAR+  , generate     -- * Queries   , lengthIndex   , length   , lookup   , head   , last-    -- * Decontruction+    -- * Deconstruction   , split-  , fold+  , take+  , takeEnd     -- * Transformation   , reverse     -- * Tuples@@ -53,16 +63,18 @@   , fromListWithDefault   ) where -import Prelude hiding ( length,lookup,replicate,head,last,zip,unzip,zipWith,reverse,foldr1 )+import Prelude hiding ( length,lookup,replicate,head,last,zip,unzip,zipWith,reverse,foldr1,take ) import qualified Prelude import Foreign.Storable (sizeOf) import Data.List (find) import Data.BinaryList.Internal import Control.Applicative (Applicative (..),(<$>)) import Control.Applicative.Backwards+import Control.Arrow ((***)) import Data.Monoid (mappend) import Data.Foldable (Foldable (..),toList) import Data.Traversable (Traversable (..))+import Control.Monad.Trans.State (evalState,get,modify)  -- | /O(1)/. Build a list with a single element. singleton :: a -> BinList a@@ -80,6 +92,11 @@ length :: BinList a -> Int length = (2^) . lengthIndex +{-# RULES+       "Data.BinaryList: length equality"+         forall xs ys . length xs == length ys = lengthIndex xs == lengthIndex ys+  #-}+ -- | /O(log n)/. Lookup an element in the list by its index (starting from 0). --   If the index is out of range, 'Nothing' is returned. lookup :: BinList a -> Int -> Maybe a@@ -108,6 +125,16 @@ split (ListNode _ l r) = Right (l,r) split (ListEnd x) = Left x +-- | /O(log n)/. Calling @take n xs@ returns the first @min (2^n) (length xs)@ elements of @xs@.+take :: Int -> BinList a -> BinList a+take k xs@(ListNode n l _) = if k >= n then xs else take k l+take _ xs = xs++-- | /O(log n)/. Calling @takeEnd n xs@ returns the last @min (2^n) (length xs)@ elements of @xs@.+takeEnd :: Int -> BinList a -> BinList a+takeEnd k xs@(ListNode n _ r) = if k >= n then xs else takeEnd k r+takeEnd _ xs = xs+ -- | /O(log n)/. Calling @replicate n x@ builds a binary list with --   @2^n@ occurences of @x@. replicate :: Int -> a -> BinList a@@ -145,6 +172,11 @@          forall i f . fmap reverse (replicateAR i f) = replicateA  i f   #-} +-- | /O(n)/. Build a binary list with the given length index (see 'lengthIndex')+--   by applying a function to each index.+generate :: Int -> (Int -> a) -> BinList a+generate l f = evalState (replicateA l $ fmap f get <* modify (+1)) 0+ -- | /O(log n)/. Get the first element of a binary list. head :: BinList a -> a head (ListNode _ l _) = head l@@ -188,6 +220,54 @@ disjoinPairsNodes (ListNode n l r) = ListNode (n-1) (disjoinPairsNodes l) (disjoinPairsNodes r) disjoinPairsNodes _ = error "disjoinPairsNodes: bug. Please, report this with an example input." +{-# RULES+      "Data.BinaryList: disjoinPairs/joinPairs"+         forall xs . disjoinPairs (joinPairs xs) = Just xs+  #-}++{-# RULES+      "Data.BinaryList: disjoinPairs/fmap/joinPairs"+         forall f xs . disjoinPairs (fmap f (joinPairs xs)) = Just (fmap (f *** f) xs)+  #-}++pairBuilder :: (a -> (b,b)) -> BinList a -> BinList b+pairBuilder f = go+  where+    go (ListEnd x) = let (a,b) = f x in ListNode 1 (ListEnd a) (ListEnd b)+    go (ListNode n l r) = ListNode (n+1) (go l) (go r)++{-# RULES+      "Data.BinaryList: joinPairs/fmap"+         forall f xs . joinPairs (fmap f xs) = pairBuilder f xs+  #-}++zipAndJoin :: ((a,b) -> (c,c)) -> BinList a -> BinList b -> BinList c+zipAndJoin f = go+  where+    -- Recursion+    go xs@(ListNode n l r) ys@(ListNode n' l' r')+         -- If both lists have the same length, recurse assuming it+         -- to avoid comparisons.+       | n == n'   = ListNode (n+1) (goEquals l l') (goEquals r r')+         -- If the first list is larger, the second fits entirely in+         -- the left branch of the first.+       | n >  n'   = go l ys+         -- If the second list is larger, the first fits entirely in+         -- the left branch of the second.+       | otherwise = go xs l'+    go xs ys       = let (x,y) = f (head xs,head ys)+                     in  ListNode 1 (ListEnd x) (ListEnd y)+    -- Recursion assuming both lists have the same length+    goEquals (ListNode n l r) (ListNode _ l' r') =+                     ListNode (n+1) (goEquals l l') (goEquals r r')+    goEquals xs ys = let (x,y) = f (head xs,head ys)+                     in  ListNode 1 (ListEnd x) (ListEnd y)++{-# RULES+      "Data.BinaryList: pairBuilder/zip"+         forall f xs ys . pairBuilder f (zip xs ys) = zipAndJoin f xs ys+  #-}+ ------------------------ -- Zipping and Unzipping @@ -223,6 +303,20 @@   let (la,lb) = unzip l       (ra,rb) = unzip r   in  (ListNode n la ra, ListNode n lb rb)++unzipMap :: ((a,b) -> (c,d)) -> BinList (a,b) -> (BinList c,BinList d)+unzipMap f = go+  where+    go (ListEnd p) = ListEnd *** ListEnd $ f p+    go (ListNode n l r) =+      let (lc,ld) = go l+          (rc,rd) = go r+      in  (ListNode n lc rc, ListNode n ld rd)++{-# RULES+      "Data.BinaryList: unzip/fmap"+         forall f xs . unzip (fmap f xs) = unzipMap f xs+  #-}  ----------------------------- -- Transforming from/to lists
Data/BinaryList/Serialize.hs view
@@ -92,7 +92,7 @@ --   lists of increasing size, ending in either a decoding error or a final --   binary list. When this is the result of 'decodeBinList', it --   contains sublists of order 1, 2, 4, 8, ... up to the order of the total---   list (unless an error has been encountered first). This sublists are+--   list (unless an error has been encountered first). These sublists are --   either a section starting at the left, or a section starting at the right, --   depending on the 'Direction' of encoding. data Decoded a = -- | Partial binary list, and rest of decoded input.
binary-list.cabal view
@@ -1,8 +1,8 @@ name:                binary-list-version:             0.3.0.0+version:             0.3.1.0 synopsis:            Lists of size length a power of two. description:         Some algorithmic problems work only when the input list-                     has length a power of two. This library provides with a+                     has length a power of two. This library implements a                      data structure optimized for this. license:             BSD3 license-file:        LICENSE