packages feed

foundation 0.0.6 → 0.0.7

raw patch · 51 files changed

+1213/−743 lines, 51 filesdep ~basePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base

API changes (from Hackage documentation)

- Foundation.Network.HostName: HostName :: String -> HostName
- Foundation.Network.HostName: HostNameInfo :: !HostName -> !(Array HostName) -> !(Array address_type) -> HostNameInfo address_type
- Foundation.Network.HostName: [addresses] :: HostNameInfo address_type -> !(Array address_type)
- Foundation.Network.HostName: [aliases] :: HostNameInfo address_type -> !(Array HostName)
- Foundation.Network.HostName: [officialName] :: HostNameInfo address_type -> !HostName
- Foundation.Network.HostName: [toString] :: HostName -> String
- Foundation.Network.HostName: data HostNameInfo address_type
- Foundation.Network.HostName: getHostNameInfo :: (Eq address_type, Storable address_type, SocketFamily address_type) => HostName -> IO (HostNameInfo address_type)
- Foundation.Network.HostName: getHostNameInfo_ :: (SocketFamily address_type, Eq address_type, Storable address_type) => Proxy address_type -> HostName -> IO (HostNameInfo address_type)
- Foundation.Network.HostName: instance Data.String.IsString Foundation.Network.HostName.HostName
- Foundation.Network.HostName: instance Foundation.Hashing.Hashable.Hashable Foundation.Network.HostName.HostName
- Foundation.Network.HostName: instance Foundation.Network.HostName.SocketFamily Foundation.Network.IPv4.IPv4
- Foundation.Network.HostName: instance Foundation.Network.HostName.SocketFamily Foundation.Network.IPv6.IPv6
- Foundation.Network.HostName: instance GHC.Classes.Eq Foundation.Network.HostName.HostName
- Foundation.Network.HostName: instance GHC.Classes.Eq Foundation.Network.HostName.HostNameError
- Foundation.Network.HostName: instance GHC.Classes.Eq address_type => GHC.Classes.Eq (Foundation.Network.HostName.HostNameInfo address_type)
- Foundation.Network.HostName: instance GHC.Classes.Ord Foundation.Network.HostName.HostName
- Foundation.Network.HostName: instance GHC.Classes.Ord address_type => GHC.Classes.Ord (Foundation.Network.HostName.HostNameInfo address_type)
- Foundation.Network.HostName: instance GHC.Exception.Exception Foundation.Network.HostName.HostNameError
- Foundation.Network.HostName: instance GHC.Show.Show Foundation.Network.HostName.HostName
- Foundation.Network.HostName: instance GHC.Show.Show Foundation.Network.HostName.HostNameError
- Foundation.Network.HostName: instance GHC.Show.Show address_type => GHC.Show.Show (Foundation.Network.HostName.HostNameInfo address_type)
- Foundation.Network.HostName: newtype HostName
+ Foundation: replicate :: Sequential c => Word -> Element c -> c
+ Foundation.Check: data PropertyCheck
+ Foundation.Check: propertyAnd :: PropertyCheck -> PropertyCheck -> PropertyCheck
+ Foundation.Check: propertyCompare :: Show a => String -> (a -> a -> Bool) -> a -> a -> PropertyCheck
+ Foundation.Check: propertyFail :: String -> PropertyCheck
+ Foundation.Collection: replicate :: Sequential c => Word -> Element c -> c
+ Foundation.String.Read: readDouble :: String -> Maybe Double
+ Foundation.String.Read: readFloatingExact :: String -> ReadFloatingCallback a -> Maybe a
+ Foundation.String.Read: readInteger :: String -> Maybe Integer
+ Foundation.String.Read: readNatural :: String -> Maybe Natural
- Foundation.Check: (===) :: Eq a => a -> a -> Property
+ Foundation.Check: (===) :: (Show a, Eq a) => a -> a -> PropertyCheck
- Foundation.Check: Prop :: Gen Bool -> Property
+ Foundation.Check: Prop :: Gen PropertyTestArg -> Property
- Foundation.Check: [unProp] :: Property -> Gen Bool
+ Foundation.Check: [unProp] :: Property -> Gen PropertyTestArg
- Foundation.Collection: (!) :: IndexedCollection c => c -> Int -> Maybe (Element c)
+ Foundation.Collection: (!) :: IndexedCollection c => c -> Offset (Element c) -> Maybe (Element c)
- Foundation.Collection: findIndex :: IndexedCollection c => (Element c -> Bool) -> c -> Maybe Int
+ Foundation.Collection: findIndex :: IndexedCollection c => (Element c -> Bool) -> c -> Maybe (Offset (Element c))

Files

Foundation.hs view
@@ -168,7 +168,7 @@ import           Foundation.Tuple  import qualified Foundation.Class.Bifunctor-import           Foundation.Internal.Types (Size(..), Offset(..))+import           Foundation.Primitive.Types.OffsetSize (Size(..), Offset(..)) import           Foundation.Internal.NumLiteral import           Foundation.Internal.Natural 
Foundation/Array/Bitmap.hs view
@@ -34,7 +34,7 @@ import           Foundation.Array.Unboxed.Mutable (MUArray) import           Foundation.Array.Common import           Foundation.Internal.Base-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Primitive.Monad import qualified Foundation.Collection as C import           Foundation.Numerical@@ -43,9 +43,9 @@ import           GHC.ST import qualified Data.List -data Bitmap = Bitmap Int (UArray Word32)+data Bitmap = Bitmap (Size Bool) (UArray Word32) -data MutableBitmap st = MutableBitmap Int (MUArray Word32 st)+data MutableBitmap st = MutableBitmap (Size Bool) (MUArray Word32 st)  bitsPerTy :: Int bitsPerTy = 32@@ -110,22 +110,23 @@     find = find     sortBy = sortBy     singleton = fromList . (:[])+    replicate n = fromList . C.replicate n  instance C.IndexedCollection Bitmap where     (!) l n-        | n < 0 || n >= length l = Nothing-        | otherwise              = Just $ index l n+        | isOutOfBound n (lengthSize l) = Nothing+        | otherwise                     = Just $ index l n     findIndex predicate c = loop 0       where-        !len = length c+        !len = lengthSize c         loop i-            | i == len                    = Nothing+            | i .==# len                  = Nothing             | predicate (unsafeIndex c i) = Just i             | otherwise                   = Nothing  instance C.MutableCollection MutableBitmap where     type MutableFreezed MutableBitmap = Bitmap-    type MutableKey MutableBitmap = Int+    type MutableKey MutableBitmap = Offset Bool     type MutableValue MutableBitmap = Bool      thaw = thaw@@ -139,8 +140,8 @@     mutWrite = write     mutRead = read -bitmapIndex :: Offset Bool -> (Int, Int)-bitmapIndex (Offset !i) = (i .>>. shiftPerTy, i .&. maskPerTy)+bitmapIndex :: Offset Bool -> (Offset Word32, Int)+bitmapIndex (Offset !i) = (Offset (i .>>. shiftPerTy), i .&. maskPerTy) {-# INLINE bitmapIndex #-}  -- return the index in word32 quantity and mask to a bit in a bitmap@@ -195,52 +196,52 @@ unsafeFreeze :: PrimMonad prim => MutableBitmap (PrimState prim) -> prim Bitmap unsafeFreeze (MutableBitmap len mba) = Bitmap len `fmap` C.unsafeFreeze mba -unsafeWrite :: PrimMonad prim => MutableBitmap (PrimState prim) -> Int -> Bool -> prim ()+unsafeWrite :: PrimMonad prim => MutableBitmap (PrimState prim) -> Offset Bool -> Bool -> prim () unsafeWrite (MutableBitmap _ ma) i v = do-    let (idx, bitIdx) = bitmapIndex (Offset i)+    let (idx, bitIdx) = bitmapIndex i     w <- A.unsafeRead ma idx     let w' = if v then setBit w bitIdx else clearBit w bitIdx     A.unsafeWrite ma idx w' {-# INLINE unsafeWrite #-} -unsafeRead :: PrimMonad prim => MutableBitmap (PrimState prim) -> Int -> prim Bool+unsafeRead :: PrimMonad prim => MutableBitmap (PrimState prim) -> Offset Bool -> prim Bool unsafeRead (MutableBitmap _ ma) i = do-    let (idx, bitIdx) = bitmapIndex (Offset i)+    let (idx, bitIdx) = bitmapIndex i     flip testBit bitIdx `fmap` A.unsafeRead ma idx {-# INLINE unsafeRead #-} -write :: PrimMonad prim => MutableBitmap (PrimState prim) -> Int -> Bool -> prim ()+write :: PrimMonad prim => MutableBitmap (PrimState prim) -> Offset Bool -> Bool -> prim () write mb n val-    | n < 0 || n >= len = primThrow (OutOfBound OOB_Write n len)-    | otherwise         = unsafeWrite mb n val+    | isOutOfBound n len = primOutOfBound OOB_Write n len+    | otherwise          = unsafeWrite mb n val   where-    len = mutableLength mb+    len = mutableLengthSize mb {-# INLINE write #-} -read :: PrimMonad prim => MutableBitmap (PrimState prim) -> Int -> prim Bool+read :: PrimMonad prim => MutableBitmap (PrimState prim) -> Offset Bool -> prim Bool read mb n-    | n < 0 || n >= len = primThrow (OutOfBound OOB_Read n len)-    | otherwise         = unsafeRead mb n-  where len = mutableLength mb+    | isOutOfBound n len = primOutOfBound OOB_Read n len+    | otherwise        = unsafeRead mb n+  where len = mutableLengthSize mb {-# INLINE read #-}  -- | Return the element at a specific index from a Bitmap. -- -- If the index @n is out of bounds, an error is raised.-index :: Bitmap -> Int -> Bool+index :: Bitmap -> Offset Bool -> Bool index bits n-    | n < 0 || n >= len = throw (OutOfBound OOB_Index n len)-    | otherwise         = unsafeIndex bits n-  where len = length bits+    | isOutOfBound n len = outOfBound OOB_Index n len+    | otherwise          = unsafeIndex bits n+  where len = lengthSize bits {-# INLINE index #-}  -- | Return the element at a specific index from an array without bounds checking. -- -- Reading from invalid memory can return unpredictable and invalid values. -- use 'index' if unsure.-unsafeIndex :: Bitmap -> Int -> Bool+unsafeIndex :: Bitmap -> Offset Bool -> Bool unsafeIndex (Bitmap _ ba) n =-    let (idx, bitIdx) = bitmapIndex (Offset n)+    let (idx, bitIdx) = bitmapIndex n      in testBit (A.unsafeIndex ba idx) bitIdx  {-# INLINE unsafeIndex #-}@@ -249,17 +250,20 @@ -- higher level collection implementation ----------------------------------------------------------------------- length :: Bitmap -> Int-length (Bitmap len _) = len+length (Bitmap (Size len) _) = len -mutableLength :: MutableBitmap st -> Int-mutableLength (MutableBitmap len _) = len+lengthSize :: Bitmap -> Size Bool+lengthSize (Bitmap sz _) = sz +mutableLengthSize :: MutableBitmap st -> Size Bool+mutableLengthSize (MutableBitmap sz _) = sz+ empty :: Bitmap empty = Bitmap 0 A.empty  new :: PrimMonad prim => Size Bool -> prim (MutableBitmap (PrimState prim))-new (Size len) =-    MutableBitmap len <$> A.new nbElements+new sz@(Size len) =+    MutableBitmap sz <$> A.new nbElements   where     nbElements :: Size Word32     nbElements = Size ((len `alignRoundUp` bitsPerTy) .>>. shiftPerTy)@@ -290,15 +294,13 @@     toPacked l =         C.foldl (.|.) 0 $ Prelude.zipWith (\b w -> if b then (1 `shiftL` w) else 0) l (C.reverse [0..31]) -}--     len        = C.length allBools  -- | transform an array to a list. vToList :: Bitmap -> [Bool] vToList a = loop 0-  where len = length a-        loop i | i == len  = []+  where len = lengthSize a+        loop i | i .==# len  = []                | otherwise = unsafeIndex a i : loop (i+1)  -- | Check if two vectors are identical@@ -307,20 +309,20 @@     | la /= lb  = False     | otherwise = loop 0   where-    !la = length a-    !lb = length b-    loop n | n == la    = True+    !la = lengthSize a+    !lb = lengthSize b+    loop n | n .==# la = True            | otherwise = (unsafeIndex a n == unsafeIndex b n) && loop (n+1)  -- | Compare 2 vectors vCompare :: Bitmap -> Bitmap -> Ordering vCompare a b = loop 0   where-    !la = length a-    !lb = length b+    !la = lengthSize a+    !lb = lengthSize b     loop n-        | n == la   = if la == lb then EQ else LT-        | n == lb   = GT+        | n .==# la = if la == lb then EQ else LT+        | n .==# lb = GT         | otherwise =             case unsafeIndex a n `compare` unsafeIndex b n of                 EQ -> loop (n+1)@@ -340,13 +342,13 @@ null (Bitmap nbBits _) = nbBits == 0  take :: Int -> Bitmap -> Bitmap-take nbElems bits@(Bitmap nbBits ba)-    | nbElems <= 0     = empty+take nbElems bits@(Bitmap (Size nbBits) ba)+    | nbElems <= 0      = empty     | nbElems >= nbBits = bits-    | otherwise        = Bitmap nbElems ba -- TODO : although it work right now, take on the underlaying ba too+    | otherwise         = Bitmap (Size nbElems) ba -- TODO : although it work right now, take on the underlaying ba too  drop :: Int -> Bitmap -> Bitmap-drop nbElems bits@(Bitmap nbBits _)+drop nbElems bits@(Bitmap (Size nbBits) _)     | nbElems <= 0      = bits     | nbElems >= nbBits = empty     | otherwise         = unoptimised (C.drop nbElems) bits@@ -364,11 +366,12 @@ break :: (Bool -> Bool) -> Bitmap -> (Bitmap, Bitmap) break predicate v = findBreak 0   where-    findBreak i-        | i == length v = (v, empty)-        | otherwise     =+    len = lengthSize v+    findBreak i@(Offset i')+        | i .==# len = (v, empty)+        | otherwise  =             if predicate (unsafeIndex v i)-                then splitAt i v+                then splitAt i' v                 else findBreak (i+1)  span :: (Bool -> Bool) -> Bitmap -> (Bitmap, Bitmap)@@ -400,10 +403,10 @@ find :: (Bool -> Bool) -> Bitmap -> Maybe Bool find predicate vec = loop 0   where-    !len = length vec+    !len = lengthSize vec     loop i-        | i == len  = Nothing-        | otherwise =+        | i .==# len = Nothing+        | otherwise  =             let e = unsafeIndex vec i              in if predicate e then Just e else loop (i+1) @@ -419,18 +422,18 @@ foldl :: (a -> Bool -> a) -> a -> Bitmap -> a foldl f initialAcc vec = loop 0 initialAcc   where-    len = length vec+    len = lengthSize vec     loop i acc-        | i == len  = acc-        | otherwise = loop (i+1) (f acc (unsafeIndex vec i))+        | i .==# len = acc+        | otherwise  = loop (i+1) (f acc (unsafeIndex vec i))  foldr :: (Bool -> a -> a) -> a -> Bitmap -> a foldr f initialAcc vec = loop 0   where-    len = length vec+    len = lengthSize vec     loop i-        | i == len  = initialAcc-        | otherwise = unsafeIndex vec i `f` loop (i+1)+        | i .==# len = initialAcc+        | otherwise  = unsafeIndex vec i `f` loop (i+1)  foldr' :: (Bool -> a -> a) -> a -> Bitmap -> a foldr' = foldr@@ -438,10 +441,10 @@ foldl' :: (a -> Bool -> a) -> a -> Bitmap -> a foldl' f initialAcc vec = loop 0 initialAcc   where-    len = length vec+    len = lengthSize vec     loop i !acc-        | i == len  = acc-        | otherwise = loop (i+1) (f acc (unsafeIndex vec i))+        | i .==# len = acc+        | otherwise  = loop (i+1) (f acc (unsafeIndex vec i))  unoptimised :: ([Bool] -> [Bool]) -> Bitmap -> Bitmap unoptimised f = vFromList . f . vToList
Foundation/Array/Boxed.hs view
@@ -10,11 +10,15 @@ {-# LANGUAGE MagicHash #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE ScopedTypeVariables #-} module Foundation.Array.Boxed     ( Array     , MArray     , empty     , length+    , lengthSize+    , mutableLength+    , mutableLengthSize     , copy     , copyAt     , unsafeCopyAtRO@@ -30,6 +34,7 @@     , read     , index     , singleton+    , replicate     , null     , take     , drop@@ -63,9 +68,11 @@ import           GHC.ST import           Foundation.Numerical import           Foundation.Internal.Base+import           Foundation.Internal.Proxy import           Foundation.Internal.MonadTrans-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Primitive.Types+import           Foundation.Primitive.IntegralConv import           Foundation.Primitive.Monad import           Foundation.Array.Common import           Foundation.Boot.Builder@@ -118,59 +125,64 @@ mutableLength (MArray _ (Size len) _) = len {-# INLINE mutableLength #-} +-- | return the numbers of elements in a mutable array+mutableLengthSize :: MArray ty st -> Size ty+mutableLengthSize (MArray _ size _) = size+{-# INLINE mutableLengthSize #-}+ -- | Return the element at a specific index from an array. -- -- If the index @n is out of bounds, an error is raised.-index :: Array ty -> Int -> ty+index :: Array ty -> Offset ty -> ty index array n-    | n < 0 || n >= len = throw (OutOfBound OOB_Index n len)-    | otherwise         = unsafeIndex array n-  where len = length array+    | isOutOfBound n len = outOfBound OOB_Index n len+    | otherwise          = unsafeIndex array n+  where len = lengthSize array {-# INLINE index #-}  -- | Return the element at a specific index from an array without bounds checking. -- -- Reading from invalid memory can return unpredictable and invalid values. -- use 'index' if unsure.-unsafeIndex :: Array ty -> Int -> ty-unsafeIndex (Array start _ a) ofs = primArrayIndex a (start+Offset ofs)+unsafeIndex :: Array ty -> Offset ty -> ty+unsafeIndex (Array start _ a) ofs = primArrayIndex a (start+ofs) {-# INLINE unsafeIndex #-}  -- | read a cell in a mutable array. -- -- If the index is out of bounds, an error is raised.-read :: PrimMonad prim => MArray ty (PrimState prim) -> Int -> prim ty+read :: PrimMonad prim => MArray ty (PrimState prim) -> Offset ty -> prim ty read array n-    | n < 0 || n >= len = primThrow (OutOfBound OOB_Read n len)-    | otherwise         = unsafeRead array n-  where len = mutableLength array+    | isOutOfBound n len = primOutOfBound OOB_Read n len+    | otherwise          = unsafeRead array n+  where len = mutableLengthSize array {-# INLINE read #-}  -- | read from a cell in a mutable array without bounds checking. -- -- Reading from invalid memory can return unpredictable and invalid values. -- use 'read' if unsure.-unsafeRead :: PrimMonad prim => MArray ty (PrimState prim) -> Int -> prim ty-unsafeRead (MArray start _ ma) i = primMutableArrayRead ma (start + Offset i)+unsafeRead :: PrimMonad prim => MArray ty (PrimState prim) -> Offset ty -> prim ty+unsafeRead (MArray start _ ma) i = primMutableArrayRead ma (start + i) {-# INLINE unsafeRead #-}  -- | Write to a cell in a mutable array. -- -- If the index is out of bounds, an error is raised.-write :: PrimMonad prim => MArray ty (PrimState prim) -> Int -> ty -> prim ()+write :: PrimMonad prim => MArray ty (PrimState prim) -> Offset ty -> ty -> prim () write array n val-    | n < 0 || n >= len = primThrow (OutOfBound OOB_Write n len)-    | otherwise         = unsafeWrite array n val-  where len = mutableLength array+    | isOutOfBound n len = primOutOfBound OOB_Write n len+    | otherwise          = unsafeWrite array n val+  where len = mutableLengthSize array {-# INLINE write #-}  -- | write to a cell in a mutable array without bounds checking. -- -- Writing with invalid bounds will corrupt memory and your program will -- become unreliable. use 'write' if unsure.-unsafeWrite :: PrimMonad prim => MArray ty (PrimState prim) -> Int -> ty -> prim ()+unsafeWrite :: PrimMonad prim => MArray ty (PrimState prim) -> Offset ty -> ty -> prim () unsafeWrite (MArray start _ ma) ofs v =-    primMutableArrayWrite ma (start + Offset ofs) v+    primMutableArrayWrite ma (start + ofs) v {-# INLINE unsafeWrite #-}  -- | Freeze a mutable array into an array.@@ -206,7 +218,7 @@     copyAt m (Offset 0) marray (Offset 0) sz     unsafeFreeze m   where-    sz = Size $ mutableLength marray+    sz = mutableLengthSize marray  -- | Copy the element to a new element array copy :: Array ty -> Array ty@@ -221,10 +233,10 @@        -> Size ty                    -- ^ number of elements to copy        -> prim () copyAt dst od src os n = loop od os-  where !endIndex = os `offsetPlusE` n-        loop (Offset d) s@(Offset i)-            | s == endIndex = return ()-            | otherwise     = unsafeRead src i >>= unsafeWrite dst d >> loop (Offset $ d+1) (Offset $ i+1)+  where -- !endIndex = os `offsetPlusE` n+        loop d s+            | s .==# n  = pure ()+            | otherwise = unsafeRead src s >>= unsafeWrite dst d >> loop (d+1) (s+1)  -- | Copy @n@ sequential elements from the specified offset in a source array --   to the specified position in a destination array.@@ -272,18 +284,17 @@  -- | Create a new array of size @n by settings each cells through the -- function @f.-create :: Int         -- ^ the size of the array-       -> (Int -> ty) -- ^ the function that set the value at the index-       -> Array ty   -- ^ the array created-create n initializer = runST (new (Size n) >>= iter initializer)+create :: forall ty . Size ty -- ^ the size of the array+       -> (Offset ty -> ty)   -- ^ the function that set the value at the index+       -> Array ty            -- ^ the array created+create n initializer = runST (new n >>= iter initializer)   where-    iter :: PrimMonad prim => (Int -> ty) -> MArray ty (PrimState prim) -> prim (Array ty)-    iter f ma = loop (Offset 0)+    iter :: PrimMonad prim => (Offset ty -> ty) -> MArray ty (PrimState prim) -> prim (Array ty)+    iter f ma = loop 0       where-        !end = Offset 0 `offsetPlusE` Size n-        loop s@(Offset i)-            | s == end  = unsafeFreeze ma-            | otherwise = unsafeWrite ma i (f i) >> loop (Offset $ i+1)+        loop s+            | s .==# n  = unsafeFreeze ma+            | otherwise = unsafeWrite ma s (f s) >> loop (s+1)         {-# INLINE loop #-}     {-# INLINE iter #-} @@ -291,22 +302,22 @@ -- higher level collection implementation ----------------------------------------------------------------------- equal :: Eq a => Array a -> Array a -> Bool-equal a b = (len == length b) && eachEqual 0+equal a b = (len == lengthSize b) && eachEqual 0   where-    len = length a+    len = lengthSize a     eachEqual !i-        | i == len                           = True+        | i .==# len                         = True         | unsafeIndex a i /= unsafeIndex b i = False         | otherwise                          = eachEqual (i+1)  vCompare :: Ord a => Array a -> Array a -> Ordering vCompare a b = loop 0   where-    !la = length a-    !lb = length b+    !la = lengthSize a+    !lb = lengthSize b     loop n-        | n == la   = if la == lb then EQ else LT-        | n == lb   = GT+        | n .==# la = if la == lb then EQ else LT+        | n .==# lb = GT         | otherwise =             case unsafeIndex a n `compare` unsafeIndex b n of                 EQ -> loop (n+1)@@ -329,16 +340,17 @@     loop i (x:xs) ma = unsafeWrite ma i x >> loop (i+1) xs ma  vToList :: Array a -> [a]-vToList v = fmap (unsafeIndex v) [0..(length v - 1)]+vToList v+    | len == 0  = []+    | otherwise = fmap (unsafeIndex v) [0..sizeLastOffset len]+  where !len = lengthSize v  -- | Append 2 arrays together by creating a new bigger array append :: Array ty -> Array ty -> Array ty append a b = runST $ do     r  <- new (la+lb)-    ma <- unsafeThaw a-    mb <- unsafeThaw b-    copyAt r (Offset 0) ma (Offset 0) la-    copyAt r (sizeAsOffset la) mb (Offset 0) lb+    unsafeCopyAtRO r (Offset 0) a (Offset 0) la+    unsafeCopyAtRO r (sizeAsOffset la) b (Offset 0) lb     unsafeFreeze r   where la = lengthSize a         lb = lengthSize b@@ -350,8 +362,7 @@     unsafeFreeze r   where loop _ _ []     = return ()         loop r i (x:xs) = do-            mx <- unsafeThaw x-            copyAt r i mx (Offset 0) lx+            unsafeCopyAtRO r i x (Offset 0) lx             loop r (i `offsetPlusE` lx) xs           where lx = lengthSize x @@ -430,11 +441,11 @@   where     !len = lengthSize vec     !endIdx = Offset 0 `offsetPlusE` len-    loop prevIdx idx@(Offset i)+    loop prevIdx idx         | idx == endIdx = [sub vec prevIdx idx]         | otherwise     =-            let e = unsafeIndex vec i-                idx' = idx + Offset 1+            let e = unsafeIndex vec idx+                idx' = idx + 1              in if predicate e                     then sub vec prevIdx idx : loop idx' idx'                     else loop prevIdx idx'@@ -450,11 +461,12 @@ break ::  (ty -> Bool) -> Array ty -> (Array ty, Array ty) break predicate v = findBreak 0   where-    findBreak i-        | i == length v = (v, empty)-        | otherwise     =+    !len = lengthSize v+    findBreak i@(Offset i')+        | i .==# len  = (v, empty)+        | otherwise   =             if predicate (unsafeIndex v i)-                then splitAt i v+                then splitAt i' v                 else findBreak (i+1)  intersperse :: ty -> Array ty -> Array ty@@ -465,20 +477,20 @@         -- terminate 1 before the end          go :: Offset ty -> ty -> Array ty -> Offset ty -> MArray ty s -> ST s ()-        go endI sep' oldV oldI@(Offset oi) newV+        go endI sep' oldV oldI newV             | oldI == endI = unsafeWrite newV dst e             | otherwise    = do                 unsafeWrite newV dst e                 unsafeWrite newV (dst + 1) sep'           where-            e = unsafeIndex oldV oi-            (Offset dst) = oldI + oldI+            e = unsafeIndex oldV oldI+            dst = oldI + oldI  span ::  (ty -> Bool) -> Array ty -> (Array ty, Array ty) span p = break (not . p)  map :: (a -> b) -> Array a -> Array b-map f a = create (length a) (\i -> f $ unsafeIndex a i)+map f a = create (sizeCast Proxy $ lengthSize a) (\i -> f $ unsafeIndex a (offsetCast Proxy i))  {- mapIndex :: (Int -> a -> b) -> Array a -> Array b@@ -491,6 +503,9 @@     unsafeWrite a 0 e     unsafeFreeze a +replicate :: Word -> ty -> Array ty+replicate sz ty = create (Size (integralCast sz)) (const ty)+ cons :: ty -> Array ty -> Array ty cons e vec     | len == Size 0 = singleton e@@ -504,14 +519,14 @@  snoc ::  Array ty -> ty -> Array ty snoc vec e-    | len == Size 0 = singleton e-    | otherwise     = runST $ do-        mv <- new (len + Size 1)-        unsafeCopyAtRO mv (Offset 0) vec (Offset 0) len-        unsafeWrite mv lastI e+    | len == 0  = singleton e+    | otherwise = runST $ do+        mv <- new (len + 1)+        unsafeCopyAtRO mv 0 vec 0 len+        unsafeWrite mv (sizeAsOffset len) e         unsafeFreeze mv   where-    !len@(Size lastI) = lengthSize vec+    !len = lengthSize vec  uncons :: Array ty -> Maybe (ty, Array ty) uncons vec@@ -523,32 +538,34 @@ unsnoc :: Array ty -> Maybe (Array ty, ty) unsnoc vec     | len == 0  = Nothing-    | otherwise = Just (take (len - 1) vec, unsafeIndex vec (len-1))+    | otherwise = Just (take (lenI - 1) vec, unsafeIndex vec (sizeLastOffset len))   where-    !len = length vec+    !len@(Size lenI) = lengthSize vec  find ::  (ty -> Bool) -> Array ty -> Maybe ty find predicate vec = loop 0   where-    !len = length vec+    !len = lengthSize vec     loop i-        | i == len  = Nothing-        | otherwise =+        | i .==# len = Nothing+        | otherwise  =             let e = unsafeIndex vec i              in if predicate e then Just e else loop (i+1) -sortBy ::  (ty -> ty -> Ordering) -> Array ty -> Array ty-sortBy xford vec = runST (thaw vec >>= doSort xford)+sortBy :: forall ty . (ty -> ty -> Ordering) -> Array ty -> Array ty+sortBy xford vec+    | len == 0  = empty+    | otherwise = runST (thaw vec >>= doSort xford)   where-    len = length vec+    len = lengthSize vec     doSort :: PrimMonad prim => (ty -> ty -> Ordering) -> MArray ty (PrimState prim) -> prim (Array ty)-    doSort ford ma = qsort 0 (len - 1) >> unsafeFreeze ma+    doSort ford ma = qsort 0 (sizeLastOffset len) >> unsafeFreeze ma       where         qsort lo hi             | lo >= hi  = return ()             | otherwise = do                 p <- partition lo hi-                qsort lo (p-1)+                qsort lo (pred p)                 qsort (p+1) hi         partition lo hi = do             pivot <- unsafeRead ma hi@@ -572,20 +589,19 @@             unsafeWrite ma i ahi             return i -filter :: (ty -> Bool) -> Array ty -> Array ty+filter :: forall ty . (ty -> Bool) -> Array ty -> Array ty filter predicate vec = runST (new len >>= copyFilterFreeze predicate (unsafeIndex vec))   where     !len = lengthSize vec-    !end = Offset 0 `offsetPlusE` len-    copyFilterFreeze :: PrimMonad prim => (ty -> Bool) -> (Int -> ty) -> MArray ty (PrimState prim) -> prim (Array ty)+    copyFilterFreeze :: PrimMonad prim => (ty -> Bool) -> (Offset ty -> ty) -> MArray ty (PrimState prim) -> prim (Array ty)     copyFilterFreeze predi getVec mvec = loop (Offset 0) (Offset 0) >>= freezeUntilIndex mvec       where-        loop d@(Offset di) s@(Offset si)-            | s == end    = return d-            | predi v     = unsafeWrite mvec di v >> loop (d+Offset 1) (s+Offset 1)-            | otherwise   = loop d (s+Offset 1)+        loop d s+            | s .==# len  = return d+            | predi v     = unsafeWrite mvec d v >> loop (d+1) (s+1)+            | otherwise   = loop d (s+1)           where-            v = getVec si+            v = getVec s  freezeUntilIndex :: PrimMonad prim => MArray ty (PrimState prim) -> Offset ty -> prim (Array ty) freezeUntilIndex mvec d = do@@ -599,36 +615,36 @@ reverse :: Array ty -> Array ty reverse a = create len toEnd   where-    len = length a-    toEnd i = unsafeIndex a (len - i - 1)+    len@(Size s) = lengthSize a+    toEnd (Offset i) = unsafeIndex a (Offset (s - 1 - i))  foldl :: (a -> ty -> a) -> a -> Array ty -> a foldl f initialAcc vec = loop 0 initialAcc   where-    len = length vec+    len = lengthSize vec     loop !i acc-        | i == len  = acc-        | otherwise = loop (i+1) (f acc (unsafeIndex vec i))+        | i .==# len = acc+        | otherwise  = loop (i+1) (f acc (unsafeIndex vec i))  foldr :: (ty -> a -> a) -> a -> Array ty -> a foldr f initialAcc vec = loop 0   where-    len = length vec+    len = lengthSize vec     loop !i-        | i == len  = initialAcc-        | otherwise = unsafeIndex vec i `f` loop (i+1)+        | i .==# len = initialAcc+        | otherwise  = unsafeIndex vec i `f` loop (i+1)  foldl' :: (a -> ty -> a) -> a -> Array ty -> a foldl' f initialAcc vec = loop 0 initialAcc   where-    len = length vec+    len = lengthSize vec     loop !i !acc-        | i == len  = acc-        | otherwise = loop (i+1) (f acc (unsafeIndex vec i))+        | i .==# len = acc+        | otherwise  = loop (i+1) (f acc (unsafeIndex vec i))  builderAppend :: PrimMonad state => ty -> Builder (Array ty) (MArray ty) ty state () builderAppend v = Builder $ State $ \(i, st) ->-    if offsetAsSize i == chunkSize st+    if i .==# chunkSize st         then do             cur      <- unsafeFreeze (curChunk st)             newChunk <- new (chunkSize st)@@ -638,9 +654,8 @@                                       , curChunk       = newChunk                                       }))         else do-            let (Offset i') = i-            unsafeWrite (curChunk st) i' v-            return ((), (i + Offset 1, st))+            unsafeWrite (curChunk st) i v+            return ((), (i+1, st))  builderBuild :: PrimMonad m => Int -> Builder (Array ty) (MArray ty) ty m () -> m (Array ty) builderBuild sizeChunksI ab
Foundation/Array/Chunked/Unboxed.hs view
@@ -1,7 +1,6 @@ -- | -- Module      : Foundation.Array.Chunked.Unboxed--- License     : BSD-style--- Maintainer  : Alfredo Di Napoli <alfredo.dinapoli@gmail.com>+-- License     : BSD-style -- Maintainer  : Alfredo Di Napoli <alfredo.dinapoli@gmail.com> -- Stability   : experimental -- Portability : portable --@@ -19,6 +18,7 @@  import qualified Data.List import           Data.Typeable+import           Control.Arrow ((***)) import           Foundation.Array.Boxed (Array) import qualified Foundation.Array.Boxed as A import           Foundation.Array.Common@@ -27,15 +27,13 @@ import           Foundation.Class.Bifunctor import qualified Foundation.Collection as C import           Foundation.Internal.Base-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Numerical-import           Foundation.Primitive.Monad import           Foundation.Primitive.Types import           GHC.ST-import qualified Prelude as P  -data ChunkedUArray ty = ChunkedUArray (Array (UArray ty))+newtype ChunkedUArray ty = ChunkedUArray (Array (UArray ty))                       deriving (Show, Ord, Typeable)  instance PrimType ty => Eq (ChunkedUArray ty) where@@ -65,6 +63,7 @@ instance PrimType ty => C.Sequential (ChunkedUArray ty) where     take = take     drop = drop+    splitAt = splitAt     revTake = revTake     revDrop = revDrop     splitOn = splitOn@@ -79,70 +78,64 @@     find = find     sortBy = sortBy     singleton = fromList . (:[])+    replicate n = fromList . C.replicate n  instance PrimType ty => C.IndexedCollection (ChunkedUArray ty) where     (!) l n-        | n < 0 || n >= length l = Nothing-        | otherwise              = Just $ index l n+        | isOutOfBound n (lengthSize l) = Nothing+        | otherwise                     = Just $ index l n     findIndex predicate c = loop 0       where-        !len = length c+        !len = lengthSize c         loop i-            | i == len  = Nothing-            | otherwise =+            | i .==# len = Nothing+            | otherwise  =                 if predicate (unsafeIndex c i) then Just i else Nothing  empty :: ChunkedUArray ty empty = ChunkedUArray (A.empty)  append :: ChunkedUArray ty -> ChunkedUArray ty -> ChunkedUArray ty-append (ChunkedUArray a1) (ChunkedUArray a2) = ChunkedUArray $ runST $ do-  let a1Size@(Size a1len) = Size $ C.length a1-  let a2Size              = Size $ C.length a2-  a <- A.new (a1Size + a2Size)-  A.thaw a1 >>= \a1' -> A.copyAt a (Offset 0) a1' (Offset 0) a1Size-  A.thaw a2 >>= \a2' -> A.copyAt a (Offset a1len) a2' (Offset 0) a2Size-  A.unsafeFreeze a+append (ChunkedUArray a1) (ChunkedUArray a2) = ChunkedUArray (mappend a1 a2)  concat :: [ChunkedUArray ty] -> ChunkedUArray ty-concat x = C.foldl' append mempty x+concat x = ChunkedUArray (mconcat $ fmap (\(ChunkedUArray spine) -> spine) x)  vFromList :: PrimType ty => [ty] -> ChunkedUArray ty-vFromList l = ChunkedUArray array-  where-    array = runST $ do-      a <- A.new (Size 1)-      A.unsafeWrite a 0 (fromList l)-      A.unsafeFreeze a+vFromList l = ChunkedUArray $ A.singleton $ fromList l  vToList :: PrimType ty => ChunkedUArray ty -> [ty] vToList (ChunkedUArray a) = mconcat $ toList $ toList <$> a  null :: PrimType ty => ChunkedUArray ty -> Bool null (ChunkedUArray array) =-  let len = C.length array-  in C.null array || allNulls 0 len+    C.null array || allNulls 0   where-    allNulls !idx len-      | idx == len = True-      | otherwise  = C.null (array `A.unsafeIndex` idx) && allNulls (idx + 1) len+    !len = A.lengthSize array+    allNulls !idx+      | idx .==# len = True+      | otherwise    = C.null (array `A.unsafeIndex` idx) && allNulls (idx + 1)  -- | Returns the length of this `ChunkedUArray`, by summing each inner length. -- Complexity: O(n) where `n` is the number of chunks, as U.length u is O(1). length :: PrimType ty => ChunkedUArray ty -> Int length (ChunkedUArray array) = C.foldl' (\acc l -> acc + C.length l) 0 array +lengthSize :: PrimType ty => ChunkedUArray ty -> Size ty+lengthSize (ChunkedUArray array) = C.foldl' (\acc l -> acc + U.lengthSize l) 0 array+ -- | Returns `True` if the given element is contained in the `ChunkedUArray`. -- Complexity: O(n) where `n` is the number of chunks, as U.length u is O(1). elem :: PrimType ty => ty -> ChunkedUArray ty -> Bool-elem el array = go 0+elem el (ChunkedUArray array) = loop 0   where-    len = C.length array-    go !currentIndex = case currentIndex < len of-      True  -> case el == array `unsafeIndex` currentIndex of-        True  -> True-        False -> go (currentIndex + 1)-      False -> False+    !len = A.lengthSize array+    loop i+        | i .==# len = False+        | otherwise  =+            case C.elem el (A.unsafeIndex array i) of+                True  -> True+                False -> loop (i+1)  -- | TODO: Improve implementation. minimum :: (Ord ty, PrimType ty) => C.NonEmpty (ChunkedUArray ty) -> ty@@ -157,128 +150,75 @@ -- equality the inner `UArray`(s), we need an element-by-element -- comparison. equal :: PrimType ty => ChunkedUArray ty -> ChunkedUArray ty -> Bool-equal ca1 ca2 = len1 == len2 && deepEqual+equal ca1 ca2 =+    len1 == len2 && go 0   where-    len1 = C.length ca1-    len2 = C.length ca2+    len1 = lengthSize ca1+    len2 = lengthSize ca2 -    deepEqual :: Bool-    deepEqual = go 0 0+    go !x+      | x .==# len1 = True+      | otherwise   = (ca1 `unsafeIndex` x == ca2 `unsafeIndex` x) && go (x + 1) -    go !x !y-      | x == len1 && y == len2 = True-      | otherwise =-        (ca1 `unsafeIndex` x == ca2 `unsafeIndex` y) && go (x + 1) (y + 1)+findPos :: PrimType ty => Offset ty -> ChunkedUArray ty -> Maybe (Offset (UArray ty), Offset ty)+findPos absOfs (ChunkedUArray array)+    | A.null array = Nothing+    | otherwise    = loop absOfs 0+  where+    !len = A.lengthSize array+    loop relOfs outerI+        | outerI .==# len = Nothing -- haven't found what to do+        | relOfs == 0     = Just (outerI, 0)+        | otherwise       =+            let !innera   = A.unsafeIndex array outerI+                !innerLen = U.lengthSize innera+             in case removeArraySize relOfs innerLen of+                        Nothing      -> Just (outerI, relOfs)+                        Just relOfs' -> loop relOfs' (outerI + 1) --- | Take the first n elements from this `ChunkedUArray`.--- TODO: Perform compaction? Compacting the underlying chunks will have--- the snag of copying data, but the pro of improving cache-friendliness--- and reduce data scattering.+splitChunk :: Offset (UArray ty) -> ChunkedUArray ty -> (ChunkedUArray ty, ChunkedUArray ty)+splitChunk (Offset ofs) (ChunkedUArray c) = (ChunkedUArray *** ChunkedUArray) $ A.splitAt ofs c+ take :: PrimType ty => Int -> ChunkedUArray ty -> ChunkedUArray ty-take nbElems v@(ChunkedUArray inner)-    | nbElems <= 0 = empty-    | C.null v     = empty-    | nbElems >= C.length v = v+take n c@(ChunkedUArray spine)+    | n <= 0    = empty     | otherwise =-      let newSize = Size requiredChunks-      in ChunkedUArray $ runST (A.new newSize >>= iter inner nbElems)-  where-    -- TODO: How can we avoid this first pass?-    requiredChunks = loop 0 nbElems-      where-        loop !idx !remaining-          | remaining <= 0 = idx-          | otherwise =-            let vec = inner `A.unsafeIndex` idx-                l = U.length vec-            in loop (idx + 1) (remaining - l)-    iter :: (PrimType ty, PrimMonad prim)-         => Array (UArray ty)-         -> Int-         -> A.MArray (UArray ty) (PrimState prim)-         -> prim (Array (UArray ty))-    iter inner0 elems finalVector = loop 0 elems-      where-        loop !currentIndex !remainingElems-          | remainingElems <= 0 || currentIndex >= C.length inner0 = A.unsafeFreeze finalVector-          | otherwise =-            let chunk = inner0 `A.unsafeIndex` currentIndex -- TODO: skip empty chunks-                chunkLen = C.length chunk-            in case C.null chunk of-              True -> loop (currentIndex + 1) remainingElems-              False -> case chunkLen <= remainingElems of-                True -> do-                  A.unsafeWrite finalVector currentIndex chunk-                  loop (currentIndex + 1) (remainingElems - chunkLen)-                False -> do-                  nc <- do-                    newChunk <- U.new (Size remainingElems)-                    U.unsafeCopyAtRO newChunk (Offset 0) chunk (Offset 0) (Size remainingElems)-                    U.unsafeFreeze newChunk-                  A.unsafeWrite finalVector currentIndex nc-                  A.freeze finalVector+        case findPos (Offset n) c of+            Nothing              -> c+            Just (Offset ofs, 0) -> ChunkedUArray (A.take ofs spine)+            Just (ofs@(Offset ofs'), (Offset r)) ->+                let uarr = A.unsafeIndex spine ofs+                 in ChunkedUArray (A.take ofs' spine `A.snoc` U.take r uarr)  drop :: PrimType ty => Int -> ChunkedUArray ty -> ChunkedUArray ty-drop nbElems v@(ChunkedUArray inner)-    | nbElems >= C.length v = empty-    | nbElems <= 0 = v-    | C.null v     = empty+drop n c@(ChunkedUArray spine)+    | n <= 0    = c     | otherwise =-      let newSize = Size (C.length inner - chunksToSkip)-      in ChunkedUArray $ runST (A.new newSize >>= iter inner nbElems)-  where-    -- TODO: How can we avoid this first pass?-    chunksToSkip = loop 0 nbElems-      where-        loop !idx !remaining =-          let vec   = inner `A.unsafeIndex` idx-              l     = U.length vec-              slack = remaining - l-          in case slack of-            x | x == 0 -> idx + 1-            x | x <  0 -> idx-            _          -> loop (idx + 1) slack-    iter :: (PrimType ty, PrimMonad prim)-         => Array (UArray ty)-         -> Int-         -> A.MArray (UArray ty) (PrimState prim)-         -> prim (Array (UArray ty))-    iter inner0 elems finalVector = loop 0 elems-      where-        -- We do not skip empty chunks, or this would screw-        -- the total, final size.-        loop !currentIndex !remainingElems-          | remainingElems <= 0 = do-            -- Copy the rest of the vector-            A.unsafeCopyAtRO finalVector (Offset 0) inner0 (Offset currentIndex) (Size $ C.length inner0 - currentIndex)-            A.freeze finalVector-          | otherwise =-            let chunk = inner0 `A.unsafeIndex` currentIndex-                chunkLen = C.length chunk-                slack    = chunkLen P.- remainingElems-            in case chunkLen <= remainingElems of-                True -> do-                  -- Skip the whole chunk-                  loop (currentIndex + 1) (remainingElems - chunkLen)-                False -> do-                  nc <- do-                    newChunk <- U.new (Size slack)-                    U.unsafeCopyAtRO newChunk (Offset 0) chunk (Offset remainingElems) (Size slack)-                    U.unsafeFreeze newChunk-                  A.unsafeWrite finalVector 0 nc-                  -- Copy the rest of the vector-                  let !nextIdx = currentIndex + 1-                  A.unsafeCopyAtRO finalVector (Offset 1) inner0 (Offset nextIdx) (Size $ C.length inner0 - nextIdx)-                  A.freeze finalVector+        case findPos (Offset n) c of+            Nothing              -> empty+            Just (Offset ofs, 0) -> ChunkedUArray (A.drop ofs spine)+            Just (ofs@(Offset ofs'), (Offset r)) ->+                let uarr = A.unsafeIndex spine ofs+                 in ChunkedUArray (U.drop r uarr `A.cons` A.drop (ofs'+1) spine) +splitAt :: PrimType ty => Int -> ChunkedUArray ty -> (ChunkedUArray ty, ChunkedUArray ty)+splitAt n c@(ChunkedUArray spine)+    | n <= 0    = (empty, c)+    | otherwise =+        case findPos (Offset n) c of+            Nothing       -> (c, empty)+            Just (ofs, 0) -> splitChunk ofs c+            Just (ofs@(Offset ofs'), (Offset r)) ->+                let uarr = A.unsafeIndex spine ofs+                 in ( ChunkedUArray (A.take ofs' spine `A.snoc` U.take r uarr)+                    , ChunkedUArray (U.drop r uarr `A.cons` A.drop (ofs'+1) spine)+                    ) --- TODO: Improve implementation. revTake :: PrimType ty => Int -> ChunkedUArray ty -> ChunkedUArray ty-revTake x = fromList . C.revTake x . toList+revTake n c = drop (length c - n) c --- TODO: Improve implementation. revDrop :: PrimType ty => Int -> ChunkedUArray ty -> ChunkedUArray ty-revDrop x = fromList . C.revDrop x . toList+revDrop n c = take (length c - n) c  -- TODO: Improve implementation. splitOn :: PrimType ty => (ty -> Bool) -> ChunkedUArray ty -> [ChunkedUArray ty]@@ -318,36 +258,38 @@   A.unsafeFreeze newArray  snoc :: PrimType ty => ChunkedUArray ty -> ty -> ChunkedUArray ty-snoc (ChunkedUArray inner) el = ChunkedUArray $ runST $ do-  newArray   <- A.new (Size $ C.length inner + 1)-  let single = fromList [el]-  A.unsafeCopyAtRO newArray (Offset 0) inner (Offset 0) (Size $ C.length inner)-  A.unsafeWrite newArray (C.length inner) single+snoc (ChunkedUArray spine) el = ChunkedUArray $ runST $ do+  newArray  <- A.new (A.lengthSize spine + 1)+  let single = U.singleton el+  A.unsafeCopyAtRO newArray (Offset 0) spine (Offset 0) (Size $ C.length spine)+  A.unsafeWrite newArray (sizeAsOffset $ A.lengthSize spine) single   A.unsafeFreeze newArray +-- TODO optimise find :: PrimType ty => (ty -> Bool) -> ChunkedUArray ty -> Maybe ty-find fn v = loop 0 (C.length v)+find fn v = loop 0   where-    loop !idx len-      | idx >= len = Nothing-      | otherwise  =+    len = lengthSize v+    loop !idx+      | idx .==# len = Nothing+      | otherwise    =         let currentElem = v `unsafeIndex` idx         in case fn currentElem of           True  -> Just currentElem-          False -> loop (idx + 1) len+          False -> loop (idx + 1)  -- TODO: Improve implementation. sortBy :: PrimType ty => (ty -> ty -> Ordering) -> ChunkedUArray ty -> ChunkedUArray ty sortBy p = fromList . C.sortBy p . toList -index :: PrimType ty => ChunkedUArray ty -> Int -> ty+index :: PrimType ty => ChunkedUArray ty -> Offset ty -> ty index array n-    | n < 0 || n >= len = throw (OutOfBound OOB_Index n len)-    | otherwise         = unsafeIndex array n-  where len = C.length array+    | isOutOfBound n len = outOfBound OOB_Index n len+    | otherwise          = unsafeIndex array n+  where len = lengthSize array {-# INLINE index #-} -unsafeIndex :: PrimType ty => ChunkedUArray ty -> Int -> ty+unsafeIndex :: PrimType ty => ChunkedUArray ty -> Offset ty -> ty unsafeIndex (ChunkedUArray array) idx = go (A.unsafeIndex array 0) 0 idx   where     go u globalIndex 0 = case C.null u of@@ -357,7 +299,14 @@     go u !globalIndex !i       -- Skip empty chunks.       | C.null u  = go (A.unsafeIndex array (globalIndex + 1)) (globalIndex + 1) i-      | otherwise = case i - (C.length u) of-        i' | i' >= 0 -> go (A.unsafeIndex array (globalIndex + 1)) (globalIndex + 1) i'-        _            -> U.unsafeIndex u i+      | otherwise =+          case removeArraySize i (U.lengthSize u) of+              Just i' -> go (A.unsafeIndex array (globalIndex + 1)) (globalIndex + 1) i'+              Nothing -> U.unsafeIndex u i+ {-# INLINE unsafeIndex #-}++removeArraySize :: Offset ty -> Size ty -> Maybe (Offset ty)+removeArraySize (Offset ty) (Size s)+    | ty >= s   = Just (Offset (ty - s))+    | otherwise = Nothing
Foundation/Array/Common.hs view
@@ -11,13 +11,17 @@ module Foundation.Array.Common     ( OutOfBound(..)     , OutOfBoundOperation(..)-+    , isOutOfBound+    , outOfBound+    , primOutOfBound     , InvalidRecast(..)     , RecastSourceSize(..)     , RecastDestinationSize(..)     ) where  import           Foundation.Internal.Base+import           Foundation.Primitive.Types.OffsetSize+import           Foundation.Primitive.Monad  -- | The type of operation that triggers an OutOfBound exception. --@@ -34,6 +38,18 @@     deriving (Show,Typeable)  instance Exception OutOfBound++outOfBound :: OutOfBoundOperation -> Offset ty -> Size ty -> a+outOfBound oobop (Offset ofs) (Size sz) = throw (OutOfBound oobop ofs sz)+{-# INLINE outOfBound #-}++primOutOfBound :: PrimMonad prim => OutOfBoundOperation -> Offset ty -> Size ty -> prim a+primOutOfBound oobop (Offset ofs) (Size sz) = primThrow (OutOfBound oobop ofs sz)+{-# INLINE primOutOfBound #-}++isOutOfBound :: Offset ty -> Size ty -> Bool+isOutOfBound (Offset ty) (Size sz) = ty < 0 || ty >= sz+{-# INLINE isOutOfBound #-}  newtype RecastSourceSize      = RecastSourceSize Int     deriving (Show,Eq,Typeable)
Foundation/Array/Unboxed.hs view
@@ -13,6 +13,8 @@ {-# LANGUAGE MagicHash #-} {-# LANGUAGE UnboxedTuples #-} {-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE Rank2Types #-} module Foundation.Array.Unboxed     ( UArray(..)     , PrimType(..)@@ -49,6 +51,8 @@     , unsafeRead     , unsafeWrite     -- * Functions+    , singleton+    , replicate     , map     , mapIndex     , findIndex@@ -95,11 +99,12 @@ import           Foundation.Internal.Base import           Foundation.Internal.Primitive import           Foundation.Internal.Proxy-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Internal.MonadTrans import qualified Foundation.Primitive.Base16 as Base16 import           Foundation.Primitive.Monad import           Foundation.Primitive.Types+import           Foundation.Primitive.IntegralConv import           Foundation.Primitive.FinalPtr import           Foundation.Primitive.Utils import           Foundation.Array.Common@@ -169,33 +174,27 @@ -- | Return the element at a specific index from an array. -- -- If the index @n is out of bounds, an error is raised.-index :: PrimType ty => UArray ty -> Int -> ty+index :: PrimType ty => UArray ty -> Offset ty -> ty index array n-    | n < 0 || n >= len = throw (OutOfBound OOB_Index n len)-    | otherwise         = unsafeIndex array n-  where len = length array+    | isOutOfBound n len = outOfBound OOB_Index n len+    | otherwise          = unsafeIndex array n+  where+    !len = lengthSize array {-# INLINE index #-}  -- | Return the element at a specific index from an array without bounds checking. -- -- Reading from invalid memory can return unpredictable and invalid values. -- use 'index' if unsure.-unsafeIndex :: PrimType ty => UArray ty -> Int -> ty-unsafeIndex (UVecBA start _ _ ba) n = primBaIndex ba (start + Offset n)-unsafeIndex v@(UVecAddr start _ fptr) n = withUnsafeFinalPtr fptr (primAddrIndex' v start)-  where-    primAddrIndex' :: PrimType ty => UArray ty -> Offset ty -> Ptr a -> IO ty-    primAddrIndex' _ start' (Ptr addr) = return (primAddrIndex addr (start' + Offset n))+unsafeIndex :: forall ty . PrimType ty => UArray ty -> Offset ty -> ty+unsafeIndex (UVecBA start _ _ ba) n = primBaIndex ba (start + n)+unsafeIndex (UVecAddr start _ fptr) n = withUnsafeFinalPtr fptr (\(Ptr addr) -> return (primAddrIndex addr (start+n)) :: IO ty) {-# INLINE unsafeIndex #-}  unsafeIndexer :: (PrimMonad prim, PrimType ty) => UArray ty -> ((Offset ty -> ty) -> prim a) -> prim a unsafeIndexer (UVecBA start _ _ ba) f = f (\n -> primBaIndex ba (start + n))-unsafeIndexer (UVecAddr start _ fptr) f = withFinalPtr fptr (\ptr -> f (primAddrIndex' start ptr))-  where-    primAddrIndex' :: PrimType ty => Offset ty -> Ptr a -> (Offset ty -> ty)-    primAddrIndex' start' (Ptr addr) = \n -> primAddrIndex addr (start' + n)-    {-# INLINE primAddrIndex' #-}-{-# NOINLINE unsafeIndexer #-}+unsafeIndexer (UVecAddr start _ fptr) f = withFinalPtr fptr $ \(Ptr addr) -> f (\n -> primAddrIndex addr (start + n))+{-# INLINE unsafeIndexer #-}  unsafeDewrap :: PrimType ty              => (ByteArray# -> Offset ty -> a)@@ -258,25 +257,25 @@     !(Size (I# nBytes)) = sizeOfE sz n unsafeCopyAtRO dst od src os n = loop od os   where-    !(Offset endIndex) = os `offsetPlusE` n-    loop (Offset d) (Offset i)+    !endIndex = os `offsetPlusE` n+    loop d i         | i == endIndex = return ()-        | otherwise     = unsafeWrite dst d (unsafeIndex src i) >> loop (Offset $ d+1) (Offset $ i+1)+        | otherwise     = unsafeWrite dst d (unsafeIndex src i) >> loop (d+1) (i+1)  -- | Allocate a new array with a fill function that has access to the elements of --   the source array.-unsafeCopyFrom :: PrimType ty-               => UArray ty -- ^ Source array-               -> Int -- ^ Length of the destination array-               -> (UArray ty -> Int -> MUArray ty s -> ST s ())+unsafeCopyFrom :: (PrimType a, PrimType b)+               => UArray a -- ^ Source array+               -> Size b -- ^ Length of the destination array+               -> (UArray a -> Offset a -> MUArray b s -> ST s ())                -- ^ Function called for each element in the source array-               -> ST s (UArray ty) -- ^ Returns the filled new array-unsafeCopyFrom v' newLen f = new (Size newLen) >>= fill 0 f >>= unsafeFreeze-  where len = length v'-        fill i f' r'-            | i == len  = return r'-            | otherwise = do f' v' i r'-                             fill (i + 1) f' r'+               -> ST s (UArray b) -- ^ Returns the filled new array+unsafeCopyFrom v' newLen f = new newLen >>= fill 0 >>= unsafeFreeze+  where len = lengthSize v'+        fill i r'+            | i .==# len = return r'+            | otherwise  = do f v' i r'+                              fill (i + 1) r'  -- | Freeze a mutable array into an array. --@@ -300,14 +299,14 @@     unsafeFreeze ma'   where len = Size $ mutableLength ma -freezeShrink :: (PrimType ty, PrimMonad prim) => MUArray ty (PrimState prim) -> Int -> prim (UArray ty)+freezeShrink :: (PrimType ty, PrimMonad prim) => MUArray ty (PrimState prim) -> Size ty -> prim (UArray ty) freezeShrink ma n = do-    ma' <- new (Size n)-    copyAt ma' (Offset 0) ma (Offset 0) (Size n)+    ma' <- new n+    copyAt ma' (Offset 0) ma (Offset 0) n     unsafeFreeze ma' -unsafeSlide :: (PrimType ty, PrimMonad prim) => MUArray ty (PrimState prim) -> Int -> Int -> prim ()-unsafeSlide mua s e = doSlide mua (Offset s) (Offset e)+unsafeSlide :: (PrimType ty, PrimMonad prim) => MUArray ty (PrimState prim) -> Offset ty -> Offset ty -> prim ()+unsafeSlide mua s e = doSlide mua s e   where     doSlide :: (PrimType ty, PrimMonad prim) => MUArray ty (PrimState prim) -> Offset ty -> Offset ty -> prim ()     doSlide (MUVecMA mbStart _ _ mba) start end  =@@ -325,19 +324,19 @@  -- | Create a new array of size @n by settings each cells through the -- function @f.-create :: PrimType ty-       => Int         -- ^ the size of the array-       -> (Int -> ty) -- ^ the function that set the value at the index-       -> UArray ty  -- ^ the array created+create :: forall ty . PrimType ty+       => Size ty           -- ^ the size of the array+       -> (Offset ty -> ty) -- ^ the function that set the value at the index+       -> UArray ty         -- ^ the array created create n initializer     | n == 0    = empty-    | otherwise = runST (new (Size n) >>= iter initializer)+    | otherwise = runST (new n >>= iter initializer)   where-    iter :: (PrimType ty, PrimMonad prim) => (Int -> ty) -> MUArray ty (PrimState prim) -> prim (UArray ty)+    iter :: (PrimType ty, PrimMonad prim) => (Offset ty -> ty) -> MUArray ty (PrimState prim) -> prim (UArray ty)     iter f ma = loop 0       where         loop i-            | i == n    = unsafeFreeze ma+            | i .==# n  = unsafeFreeze ma             | otherwise = unsafeWrite ma i (f i) >> loop (i+1)         {-# INLINE loop #-}     {-# INLINE iter #-}@@ -365,8 +364,11 @@ empty = UVecAddr (Offset 0) (Size 0) (FinalPtr $ error "empty de-referenced")  singleton :: PrimType ty => ty -> UArray ty-singleton ty = create 1 (\_ -> ty)+singleton ty = create 1 (const ty) +replicate :: PrimType ty => Word -> ty -> UArray ty+replicate sz ty = create (Size (integralCast sz)) (const ty)+ -- | make an array from a list of elements. vFromList :: PrimType ty => [ty] -> UArray ty vFromList l = runST $ do@@ -374,22 +376,26 @@     iter 0 l $ \i x -> unsafeWrite ma i x     unsafeFreeze ma   where len = Data.List.length l-        iter _ [] _ = return ()-        iter i (x:xs) z = z i x >> iter (i+1) xs z+        iter _  []     _ = return ()+        iter !i (x:xs) z = z i x >> iter (i+1) xs z  -- | transform an array to a list.-vToList :: PrimType ty => UArray ty -> [ty]+vToList :: forall ty . PrimType ty => UArray ty -> [ty] vToList a-    | null a    = []-    | otherwise = runST (unsafeIndexer a go)+    | len == 0  = []+    | otherwise = unsafeDewrap goBa goPtr a   where-    !len = length a-    go :: (Offset ty -> ty) -> ST s [ty]-    go getIdx = return $ loop azero+    !len = lengthSize a+    goBa ba start = loop start       where-        loop i | i == Offset len = []-               | otherwise        = getIdx i : loop (i+Offset 1)-    {-# INLINE go #-}+        !end = start `offsetPlusE` len+        loop !i | i == end  = []+                | otherwise = primBaIndex ba i : loop (i+1)+    goPtr (Ptr addr) start = pureST (loop start)+      where+        !end = start `offsetPlusE` len+        loop !i | i == end  = []+                | otherwise = primAddrIndex addr i : loop (i+1)  -- | Check if two vectors are identical equal :: (PrimType ty, Eq ty) => UArray ty -> UArray ty -> Bool@@ -397,9 +403,9 @@     | la /= lb  = False     | otherwise = loop 0   where-    !la = length a-    !lb = length b-    loop n | n == la    = True+    !la = lengthSize a+    !lb = lengthSize b+    loop n | n .==# la = True            | otherwise = (unsafeIndex a n == unsafeIndex b n) && loop (n+1)  {-@@ -411,11 +417,11 @@ vCompare :: (Ord ty, PrimType ty) => UArray ty -> UArray ty -> Ordering vCompare a b = loop 0   where-    !la = length a-    !lb = length b+    !la = lengthSize a+    !lb = lengthSize b     loop n-        | n == la   = if la == lb then EQ else LT-        | n == lb   = GT+        | n .==# la = if la == lb then EQ else LT+        | n .==# lb = GT         | otherwise =             case unsafeIndex a n `compare` unsafeIndex b n of                 EQ -> loop (n+1)@@ -466,7 +472,7 @@ -- the operation copy the previous array, modify it in place, then freeze it. update :: PrimType ty        => UArray ty-       -> [(Int, ty)]+       -> [(Offset ty, ty)]        -> UArray ty update array modifiers = runST (thaw array >>= doUpdate modifiers)   where doUpdate l ma = loop l@@ -477,7 +483,7 @@  unsafeUpdate :: PrimType ty              => UArray ty-             -> [(Int, ty)]+             -> [(Offset ty, ty)]              -> UArray ty unsafeUpdate array modifiers = runST (thaw array >>= doUpdate modifiers)   where doUpdate l ma = loop l@@ -616,33 +622,36 @@ splitOn :: PrimType ty => (ty -> Bool) -> UArray ty -> [UArray ty] splitOn xpredicate ivec     | len == 0  = [mempty]-    | otherwise = runST $ unsafeIndexer ivec (go ivec xpredicate)+    | otherwise = runST $ unsafeIndexer ivec (pureST . go ivec xpredicate)   where-    !len = length ivec-    go :: PrimType ty => UArray ty -> (ty -> Bool) -> (Offset ty -> ty) -> ST s [UArray ty]-    go v predicate getIdx = return (loop azero azero)+    !len = lengthSize ivec+    --go :: PrimType ty => UArray ty -> (ty -> Bool) -> (Offset ty -> ty) -> ST s [UArray ty]+    go v predicate getIdx = loop 0 0       where-        loop !prevIdx@(Offset prevIdxo) !idx@(Offset idxo)-            | idx == Offset len = [sub v prevIdxo idxo]-            | otherwise          =+        loop !prevIdx !idx+            | idx .==# len = [sub v prevIdx idx]+            | otherwise    =                 let e = getIdx idx-                    idx' = idx + Offset 1+                    idx' = idx + 1                  in if predicate e-                        then sub v prevIdxo idxo : loop idx' idx'+                        then sub v prevIdx idx : loop idx' idx'                         else loop prevIdx idx'     {-# INLINE go #-} -sub :: PrimType ty => UArray ty -> Int -> Int -> UArray ty+pureST :: a -> ST s a+pureST = pure++sub :: PrimType ty => UArray ty -> Offset ty -> Offset ty -> UArray ty sub vec startIdx expectedEndIdx     | startIdx >= endIdx = empty     | otherwise          =         case vec of-            UVecBA start _ pinst ba -> UVecBA (start + Offset startIdx) newLen pinst ba-            UVecAddr start _ fptr   -> UVecAddr (start + Offset startIdx) newLen fptr+            UVecBA start _ pinst ba -> UVecBA (start + startIdx) newLen pinst ba+            UVecAddr start _ fptr   -> UVecAddr (start + startIdx) newLen fptr   where-    newLen = Offset endIdx - Offset startIdx-    endIdx = min expectedEndIdx len-    len = length vec+    newLen = endIdx - startIdx+    endIdx = min expectedEndIdx (0 `offsetPlusE` len)+    len = lengthSize vec  findIndex :: PrimType ty => ty -> UArray ty -> Maybe Int findIndex tyOuter ba = runST $ unsafeIndexer ba (go tyOuter)@@ -709,36 +718,40 @@         where t                  = primAddrIndex addr i {-# SPECIALIZE [2] elem :: Word8 -> UArray Word8 -> Bool #-} -intersperse :: PrimType ty => ty -> UArray ty -> UArray ty+intersperse :: forall ty . PrimType ty => ty -> UArray ty -> UArray ty intersperse sep v     | len <= 1  = v-    | otherwise = runST $ unsafeCopyFrom v (len * 2 - 1) (go sep)-  where len = length v-        go :: PrimType ty => ty -> UArray ty -> Int -> MUArray ty s -> ST s ()-        go sep' oldV oldI newV-            | oldI == len - 1 = unsafeWrite newV newI e-            | otherwise       = do-                unsafeWrite newV newI e-                unsafeWrite newV (newI + 1) sep'-          where-            e = unsafeIndex oldV oldI-            newI = oldI * 2+    | otherwise = runST $ unsafeCopyFrom v newSize (go sep)+  where+    len = lengthSize v+    newSize = (scale (2:: Word) len) - 1 +    go :: PrimType ty => ty -> UArray ty -> Offset ty -> MUArray ty s -> ST s ()+    go sep' oldV oldI newV+        | oldI .==# (len - 1) = unsafeWrite newV newI e+        | otherwise           = do+            unsafeWrite newV newI e+            unsafeWrite newV (newI + 1) sep'+      where+        e = unsafeIndex oldV oldI+        newI = scale (2 :: Word) oldI+ span :: PrimType ty => (ty -> Bool) -> UArray ty -> (UArray ty, UArray ty) span p = break (not . p)  map :: (PrimType a, PrimType b) => (a -> b) -> UArray a -> UArray b-map f a = create (length a) (\i -> f $ unsafeIndex a i)+map f a = create lenB (\i -> f $ unsafeIndex a (offsetCast Proxy i))+  where !lenB = sizeCast (Proxy :: Proxy (a -> b)) (lengthSize a) -mapIndex :: (PrimType a, PrimType b) => (Int -> a -> b) -> UArray a -> UArray b-mapIndex f a = create (length a) (\i -> f i $ unsafeIndex a i)+mapIndex :: (PrimType a, PrimType b) => (Offset b -> a -> b) -> UArray a -> UArray b+mapIndex f a = create (sizeCast Proxy $ lengthSize a) (\i -> f i $ unsafeIndex a (offsetCast Proxy i))  cons :: PrimType ty => ty -> UArray ty -> UArray ty cons e vec     | len == Size 0 = singleton e     | otherwise     = runST $ do-        muv <- new (len + Size 1)-        unsafeCopyAtRO muv (Offset 1) vec (Offset 0) len+        muv <- new (len + 1)+        unsafeCopyAtRO muv 1 vec 0 len         unsafeWrite muv 0 e         unsafeFreeze muv   where@@ -750,7 +763,7 @@     | otherwise     = runST $ do         muv <- new (len + Size 1)         unsafeCopyAtRO muv (Offset 0) vec (Offset 0) len-        unsafeWrite muv (length vec) e+        unsafeWrite muv (0 `offsetPlusE` lengthSize vec) e         unsafeFreeze muv   where      !len = lengthSize vec@@ -758,40 +771,42 @@ uncons :: PrimType ty => UArray ty -> Maybe (ty, UArray ty) uncons vec     | nbElems == 0 = Nothing-    | otherwise    = Just (unsafeIndex vec 0, sub vec 1 nbElems)+    | otherwise    = Just (unsafeIndex vec 0, sub vec 1 (0 `offsetPlusE` nbElems))   where-    !nbElems = length vec+    !nbElems = lengthSize vec  unsnoc :: PrimType ty => UArray ty -> Maybe (UArray ty, ty) unsnoc vec     | nbElems == 0 = Nothing     | otherwise    = Just (sub vec 0 lastElem, unsafeIndex vec lastElem)   where-    !lastElem = nbElems - 1-    !nbElems = length vec+    !lastElem = 0 `offsetPlusE` (nbElems - 1)+    !nbElems = lengthSize vec  find :: PrimType ty => (ty -> Bool) -> UArray ty -> Maybe ty find predicate vec = loop 0   where-    !len = length vec+    !len = lengthSize vec     loop i-        | i == len  = Nothing-        | otherwise =+        | i .==# len = Nothing+        | otherwise  =             let e = unsafeIndex vec i              in if predicate e then Just e else loop (i+1) -sortBy :: PrimType ty => (ty -> ty -> Ordering) -> UArray ty -> UArray ty-sortBy xford vec = runST (thaw vec >>= doSort xford)+sortBy :: forall ty . PrimType ty => (ty -> ty -> Ordering) -> UArray ty -> UArray ty+sortBy xford vec+    | len == 0  = empty+    | otherwise = runST (thaw vec >>= doSort xford)   where-    len = length vec+    len = lengthSize vec     doSort :: (PrimType ty, PrimMonad prim) => (ty -> ty -> Ordering) -> MUArray ty (PrimState prim) -> prim (UArray ty)-    doSort ford ma = qsort 0 (len - 1) >> unsafeFreeze ma+    doSort ford ma = qsort 0 (sizeLastOffset len) >> unsafeFreeze ma       where         qsort lo hi             | lo >= hi  = return ()             | otherwise = do                 p <- partition lo hi-                qsort lo (p-1)+                qsort lo (pred p)                 qsort (p+1) hi         partition lo hi = do             pivot <- unsafeRead ma hi@@ -849,26 +864,26 @@ foldl :: PrimType ty => (a -> ty -> a) -> a -> UArray ty -> a foldl f initialAcc vec = loop 0 initialAcc   where-    len = length vec+    len = lengthSize vec     loop i acc-        | i == len  = acc-        | otherwise = loop (i+1) (f acc (unsafeIndex vec i))+        | i .==# len = acc+        | otherwise  = loop (i+1) (f acc (unsafeIndex vec i))  foldr :: PrimType ty => (ty -> a -> a) -> a -> UArray ty -> a foldr f initialAcc vec = loop 0   where-    len = length vec+    !len = lengthSize vec     loop i-        | i == len  = initialAcc-        | otherwise = unsafeIndex vec i `f` loop (i+1)+        | i .==# len = initialAcc+        | otherwise  = unsafeIndex vec i `f` loop (i+1)  foldl' :: PrimType ty => (a -> ty -> a) -> a -> UArray ty -> a foldl' f initialAcc vec = loop 0 initialAcc   where-    len = length vec+    !len = lengthSize vec     loop i !acc-        | i == len  = acc-        | otherwise = loop (i+1) (f acc (unsafeIndex vec i))+        | i .==# len = acc+        | otherwise  = loop (i+1) (f acc (unsafeIndex vec i))  builderAppend :: (PrimType ty, PrimMonad state) => ty -> Builder (UArray ty) (MUArray ty) ty state () builderAppend v = Builder $ State $ \(i, st) ->@@ -882,9 +897,8 @@                                       , curChunk       = newChunk                                       }))         else do-            let Offset i' = i-            unsafeWrite (curChunk st) i' v-            return ((), (i + Offset 1, st))+            unsafeWrite (curChunk st) i v+            return ((), (i + 1, st))  builderBuild :: (PrimType ty, PrimMonad m) => Int -> Builder (UArray ty) (MUArray ty) ty m () -> m (UArray ty) builderBuild sizeChunksI ab
Foundation/Array/Unboxed/ByteArray.hs view
@@ -1,15 +1,14 @@ module Foundation.Array.Unboxed.ByteArray     ( MutableByteArray     , mutableByteArraySet-    , mutableByteArraySetBetween-    , mutableByteArrayMove+    -- , mutableByteArraySetBetween+    -- , mutableByteArrayMove     ) where  import Foundation.Internal.Base+import Foundation.Primitive.Types.OffsetSize import Foundation.Primitive.Monad-import Foundation.Array.Common import Foundation.Array.Unboxed.Mutable-import Foundation.Numerical import Control.Monad (forM_)  -- | Mutable Byte Array alias@@ -18,19 +17,21 @@ mutableByteArraySet :: PrimMonad prim => MUArray Word8 (PrimState prim) -> Word8 -> prim () mutableByteArraySet mba val = do     -- naive haskell way. TODO: call memset or a 32-bit/64-bit method-    forM_ [0..(len-1)] $ \i -> unsafeWrite mba i val+    forM_ [0..(sizeLastOffset len)] $ \i -> unsafeWrite mba i val   where-    len = mutableLength mba+    len = mutableLengthSize mba -mutableByteArraySetBetween :: PrimMonad prim => MUArray Word8 (PrimState prim) -> Word8 -> Int -> Int -> prim ()+{-+mutableByteArraySetBetween :: PrimMonad prim => MUArray Word8 (PrimState prim) -> Word8 -> Offset Word8 -> Size Word8 -> prim () mutableByteArraySetBetween mba val offset size-    | offset < 0                        = throw (OutOfBound OOB_MemSet offset len)-    | offset > len || offset+size > len = throw (OutOfBound OOB_MemSet (offset+size) len)+    | offset < 0                        = primOutOfBound OOB_MemSet offset                      len+    | offset > len || offset+size > len = primOutOfBound OOB_MemSet (offset `OffsetPlusE` size) len     | otherwise =         -- TODO same as mutableByteArraySet-        forM_ [offset..(offset+size-1)] $ \i -> unsafeWrite mba i val+        forM_ [offset..(offset + sizeLastOffset size)] $ \i -> unsafeWrite mba i val   where-    len = mutableLength mba+    len = mutableLengthSize mba  mutableByteArrayMove :: PrimMonad prim => MUArray Word8 (PrimState prim) -> Int -> Int -> Int -> prim () mutableByteArrayMove _mba _ofs _sz = undefined+    -}
Foundation/Array/Unboxed/Mutable.hs view
@@ -18,6 +18,7 @@     -- * Property queries     , sizeInMutableBytesOfContent     , mutableLength+    , mutableLengthSize     , mutableSame     -- * Allocation & Copy     , new@@ -40,9 +41,9 @@ import           GHC.Ptr import           Foundation.Internal.Base import qualified Foundation.Internal.Environment as Environment-import           Foundation.Internal.Types import           Foundation.Internal.Primitive import           Foundation.Internal.Proxy+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Primitive.Monad import           Foundation.Primitive.Types import           Foundation.Primitive.FinalPtr@@ -75,40 +76,40 @@ -- | read a cell in a mutable array. -- -- If the index is out of bounds, an error is raised.-read :: (PrimMonad prim, PrimType ty) => MUArray ty (PrimState prim) -> Int -> prim ty+read :: (PrimMonad prim, PrimType ty) => MUArray ty (PrimState prim) -> Offset ty -> prim ty read array n-    | n < 0 || n >= len = primThrow (OutOfBound OOB_Read n len)-    | otherwise         = unsafeRead array n-  where len = mutableLength array+    | isOutOfBound n len = primOutOfBound OOB_Read n len+    | otherwise          = unsafeRead array n+  where len = mutableLengthSize array {-# INLINE read #-}  -- | read from a cell in a mutable array without bounds checking. -- -- Reading from invalid memory can return unpredictable and invalid values. -- use 'read' if unsure.-unsafeRead :: (PrimMonad prim, PrimType ty) => MUArray ty (PrimState prim) -> Int -> prim ty-unsafeRead (MUVecMA start _ _ mba) i = primMbaRead mba (start+.i)-unsafeRead (MUVecAddr start _ fptr) i = withFinalPtr fptr $ \(Ptr addr) -> primAddrRead addr (start+.i)+unsafeRead :: (PrimMonad prim, PrimType ty) => MUArray ty (PrimState prim) -> Offset ty -> prim ty+unsafeRead (MUVecMA start _ _ mba) i = primMbaRead mba (start + i)+unsafeRead (MUVecAddr start _ fptr) i = withFinalPtr fptr $ \(Ptr addr) -> primAddrRead addr (start + i) {-# INLINE unsafeRead #-}  -- | Write to a cell in a mutable array. -- -- If the index is out of bounds, an error is raised.-write :: (PrimMonad prim, PrimType ty) => MUArray ty (PrimState prim) -> Int -> ty -> prim ()+write :: (PrimMonad prim, PrimType ty) => MUArray ty (PrimState prim) -> Offset ty -> ty -> prim () write array n val-    | n < 0 || n >= len = primThrow (OutOfBound OOB_Write n len)-    | otherwise         = unsafeWrite array n val+    | isOutOfBound n len = primOutOfBound OOB_Write n len+    | otherwise          = unsafeWrite array n val   where-    len = mutableLength array+    len = mutableLengthSize array {-# INLINE write #-}  -- | write to a cell in a mutable array without bounds checking. -- -- Writing with invalid bounds will corrupt memory and your program will -- become unreliable. use 'write' if unsure.-unsafeWrite :: (PrimMonad prim, PrimType ty) => MUArray ty (PrimState prim) -> Int -> ty -> prim ()-unsafeWrite (MUVecMA start _ _ mba)  i v = primMbaWrite mba (start+.i) v-unsafeWrite (MUVecAddr start _ fptr) i v = withFinalPtr fptr $ \(Ptr addr) -> primAddrWrite addr (start+.i) v+unsafeWrite :: (PrimMonad prim, PrimType ty) => MUArray ty (PrimState prim) -> Offset ty -> ty -> prim ()+unsafeWrite (MUVecMA start _ _ mba)  i v = primMbaWrite mba (start+i) v+unsafeWrite (MUVecAddr start _ fptr) i v = withFinalPtr fptr $ \(Ptr addr) -> primAddrWrite addr (start+i) v {-# INLINE unsafeWrite #-}  -- | Create a new pinned mutable array of size @n.@@ -203,10 +204,10 @@     !(Size (I# nBytes)) = sizeOfE sz n copyAt dst od src os n = loop od os   where-    !(Offset endIndex) = os `offsetPlusE` n-    loop !(Offset d) !(Offset i)+    !endIndex = os `offsetPlusE` n+    loop !d !i         | i == endIndex = return ()-        | otherwise     = unsafeRead src i >>= unsafeWrite dst d >> loop (Offset $ d+1) (Offset $ i+1)+        | otherwise     = unsafeRead src i >>= unsafeWrite dst d >> loop (d+1) (i+1)  sub :: (PrimMonad prim, PrimType ty)     => MUArray ty (PrimState prim)@@ -248,6 +249,10 @@ mutableLength :: PrimType ty => MUArray ty st -> Int mutableLength (MUVecMA _ (Size end) _ _) = end mutableLength (MUVecAddr _ (Size end) _) = end++mutableLengthSize :: PrimType ty => MUArray ty st -> Size ty+mutableLengthSize (MUVecMA _ end _ _) = end+mutableLengthSize (MUVecAddr _ end _) = end  withMutablePtrHint :: (PrimMonad prim, PrimType ty)                    => Bool
Foundation/Boot/Builder.hs view
@@ -6,7 +6,7 @@  import           Foundation.Internal.Base import           Foundation.Internal.MonadTrans-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Primitive.Monad  newtype Builder collection mutCollection step state a = Builder
Foundation/Check.hs view
@@ -13,9 +13,13 @@     , Test(..)     , testName     -- * Property+    , PropertyCheck     , Property(..)     , IsProperty(..)     , (===)+    , propertyCompare+    , propertyAnd+    , propertyFail     -- * As Program     , defaultMain     ) where@@ -28,6 +32,7 @@ import           Foundation.Check.Gen import           Foundation.Check.Arbitrary import           Foundation.Check.Property+import           Foundation.Random import           Foundation.Monad import           Control.Exception (evaluate, SomeException) import           System.Exit@@ -76,27 +81,56 @@ nbFail (PropertyResult _ _ PropertySuccess)    = 0 nbFail (GroupResult    _ t _)                  = t -runProp :: Context -> String -> Property -> IO TestResult-runProp ctx s prop = do-    (\(e, i) -> PropertyResult s i e) <$> iterProp 0+-- | return the number of tests runned and the result+runProp :: Context -> String -> Property -> IO (PropertyResult, Word64)+runProp ctx s prop = iterProp 1   where     nbTests = 100     iterProp :: Word64 -> IO (PropertyResult, Word64)     iterProp i-        | i == nbTests = return (PropertySuccess, nbTests)+        | i == nbTests = return (PropertySuccess, i)         | otherwise    = do             r <- toResult i             case r of-                PropertyFailed e -> return (PropertyFailed e, i)-                PropertySuccess  -> iterProp (i+1)-    toResult :: Word64 -> IO PropertyResult+                (PropertyFailed e, _)               -> return (PropertyFailed e, i)+                (PropertySuccess, cont) | cont      -> iterProp (i+1)+                                        | otherwise -> return (PropertySuccess, i)+    toResult :: Word64 -> IO (PropertyResult, Bool)     toResult it =                 (propertyToResult <$> evaluate (runGen (unProp prop) (rngIt it) params))-        `catch` (\(e :: SomeException) -> return $ PropertyFailed (fromList $ show e))+        `catch` (\(e :: SomeException) -> return (PropertyFailed (fromList $ show e), False)) -    propertyToResult False = PropertyFailed "property failed"-    propertyToResult True  = PropertySuccess+    propertyToResult p =+        let args   = getArgs p+            checks = getChecks p+         in if checkHasFailed checks+                then printError args checks+                else (PropertySuccess, length args > 0) +    printError args checks = (PropertyFailed (mconcat $ loop 1 args), False)+      where+        loop :: Word -> [String] -> [String]+        loop _ []      = printChecks checks+        loop !i (a:as) = "parameter " <> fromList (show i) <> " : " <> a <> "\n" : loop (i+1) as+    printChecks (PropertyBinaryOp True name _ _)  = []+    printChecks (PropertyBinaryOp False name a b) = [name <> " checked fail\n" <> "   left: " <> a <> "\n" <> "  right: " <> b]+    printChecks (PropertyNamed True _)            = []+    printChecks (PropertyNamed False name)        = ["Check " <> name <> " failed"]+    printChecks (PropertyBoolean True)            = []+    printChecks (PropertyBoolean False)           = ["Check failed"]+    printChecks (PropertyFail _ e)                = ["Check failed: " <> e]+    printChecks (PropertyAnd True _ _)            = []+    printChecks (PropertyAnd False a1 a2)+        | checkHasFailed a1 && checkHasFailed a2  = ["And Property failed:\n    && left: "] <> printChecks a1 <> ["\n"] <> ["   && right: "] <> printChecks a2+        | checkHasFailed a1                       = ["And Property failed:\n    && left: "] <> printChecks a1 <> ["\n"]+        | otherwise                               = ["And Property failed:\n   && right: "] <> printChecks a2 <> ["\n"]++    getArgs (PropertyArg a p) = a : getArgs p+    getArgs (PropertyEOA _) = []++    getChecks (PropertyArg _ p) = getChecks p+    getChecks (PropertyEOA c  ) = c+     !rngIt  = genRng (contextSeed ctx) (s : contextGroups ctx)     !params = GenParams { genMaxSizeIntegral = 32   -- 256 bits maximum numbers                         , genMaxSizeArray    = 512  -- 512 elements@@ -108,8 +142,10 @@ defaultMain test = do     -- parse arguments     --let arguments = [ "seed", "j" ]-    let seed = 10 +    -- generate a new seed+    seed <- getRandomPrimType+     let context = Context { contextLevel  = 0                           , contextGroups = []                           , contextSeed   = seed@@ -126,13 +162,17 @@      runTest :: Context -> Test -> IO TestResult     runTest ctx (Group s l) = do-        putStrLn s+        printIndent ctx s         results <- mapM (runTest (appendContext s ctx)) l         return $ GroupResult s (foldl' (+) 0 $ fmap nbFail results) results     runTest ctx (Property name prop) = do-        v <- runProp ctx name (property prop)-        putStrLn $ fromList (show v)-        return v+        (res, nbTests) <- runProp ctx name (property prop)+        case res of+            PropertySuccess  -> printIndent ctx $ "[  OK   ]   " <> name <> " (" <> fromList (show nbTests) <> " completed)"+            PropertyFailed e -> printIndent ctx $ "[ ERROR ]   " <> name <> " after " <> fromList (show (nbTests-1)) <> " tests\n" <> e+        return (PropertyResult name nbTests res)      runTest _ (Unit _ _) = do         error "not implemented"++    printIndent ctx s = putStrLn (replicate (contextLevel ctx) ' ' <> s)
Foundation/Check/Arbitrary.hs view
@@ -12,6 +12,7 @@ import           Foundation.Internal.Natural import           Foundation.Primitive import           Foundation.Primitive.IntegralConv (wordToChar)+import           Foundation.Primitive.Floating (integerToDouble, naturalToDouble, doubleExponant) import           Foundation.Check.Gen import           Foundation.Random import           Foundation.Bits@@ -60,6 +61,11 @@ instance Arbitrary String where     arbitrary = genWithParams $ \params ->         fromList <$> (genMax (genMaxSizeString params) >>= \i -> replicateM (integralCast i) arbitrary)++instance Arbitrary Double where+    arbitrary = toDouble <$> arbitrary <*> arbitrary <*> arbitrary+      where toDouble i n Nothing  = integerToDouble i + (naturalToDouble n / 100000)+            toDouble i n (Just e) = (integerToDouble i + (naturalToDouble n / 1000000)) * (integerToDouble e)  instance Arbitrary a => Arbitrary (Maybe a) where     arbitrary = frequency $ nonEmpty_ [ (1, pure Nothing), (4, Just <$> arbitrary) ]
Foundation/Check/Property.hs view
@@ -1,33 +1,93 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE FlexibleInstances #-} module Foundation.Check.Property     ( Property(..)+    , PropertyTestArg(..)     , IsProperty+    , PropertyCheck(..)     , property+    , checkHasSucceed+    , checkHasFailed     -- * Properties     , forAll     , (===)+    , propertyCompare+    , propertyAnd+    , propertyFail     ) where  import Foundation.Internal.Base import Foundation.Check.Gen import Foundation.Check.Arbitrary+import Foundation.String +type PropertyTestResult = Bool++-- | The type of check this test did for a property+data PropertyCheck = PropertyBoolean  PropertyTestResult+                   | PropertyNamed    PropertyTestResult String+                   | PropertyBinaryOp PropertyTestResult String String String+                   | PropertyAnd      PropertyTestResult PropertyCheck PropertyCheck+                   | PropertyFail     PropertyTestResult String++checkHasSucceed :: PropertyCheck -> PropertyTestResult+checkHasSucceed (PropertyBoolean b)        = b+checkHasSucceed (PropertyNamed b _)        = b+checkHasSucceed (PropertyBinaryOp b _ _ _) = b+checkHasSucceed (PropertyAnd b _ _)        = b+checkHasSucceed (PropertyFail b _)         = b++checkHasFailed :: PropertyCheck -> PropertyTestResult+checkHasFailed = not . checkHasSucceed++-- | A linked-list of arguments to this test+data PropertyTestArg = PropertyEOA PropertyCheck+                     | PropertyArg String PropertyTestArg++data Property = Prop { unProp :: Gen PropertyTestArg }+ class IsProperty p where     property :: p -> Property  instance IsProperty Bool where-    property b = Prop (pure b)+    property b = Prop $ pure (PropertyEOA $ PropertyBoolean b)+instance IsProperty (String, Bool) where+    property (name, b) = Prop $ pure (PropertyEOA $ PropertyNamed b name)+instance IsProperty PropertyCheck where+    property check = Prop $ pure (PropertyEOA check) instance IsProperty Property where-    property p = p -- (Prop result) = Prop . return $ result-instance IsProperty prop => IsProperty (Gen prop) where-    property mp = Prop (mp >>= \p -> unProp (property p))-instance (Arbitrary a, IsProperty prop) => IsProperty (a -> prop) where+    property p = p+instance (Show a, Arbitrary a, IsProperty prop) => IsProperty (a -> prop) where     property p = forAll arbitrary p -data Property = Prop { unProp :: Gen Bool }--forAll :: IsProperty prop => Gen a -> (a -> prop) -> Property-forAll generator tst = Prop (generator >>= \a -> unProp (property (tst a)))+forAll :: (Show a, IsProperty prop) => Gen a -> (a -> prop) -> Property+forAll generator tst = Prop $ do+    a <- generator+    augment a <$> unProp (property (tst a))+  where+    augment a arg = PropertyArg (fromList $ show a) arg -(===) :: Eq a => a -> a -> Property-(===) a b = Prop (pure (a == b))+(===) :: (Show a, Eq a) => a -> a -> PropertyCheck+(===) a b =+    let sa = fromList (show a)+        sb = fromList (show b)+     in PropertyBinaryOp (a == b) "==" sa sb infix 4 ===++propertyCompare :: Show a+                => String           -- ^ name of the function used for comparaison, e.g. (<)+                -> (a -> a -> Bool) -- ^ function used for value comparaison+                -> a                -- ^ value left of the operator+                -> a                -- ^ value right of the operator+                -> PropertyCheck+propertyCompare name op a b =+    let sa = fromList (show a)+        sb = fromList (show b)+     in PropertyBinaryOp (a `op` b) name sa sb++propertyAnd :: PropertyCheck -> PropertyCheck -> PropertyCheck+propertyAnd c1 c2 =+    PropertyAnd (checkHasSucceed c1 && checkHasSucceed c2) c1 c2++propertyFail :: String -> PropertyCheck+propertyFail = PropertyFail False
Foundation/Class/Storable.hs view
@@ -35,7 +35,7 @@ import           Foreign.C.Types (CChar, CUChar)  import Foundation.Internal.Base-import Foundation.Internal.Types+import Foundation.Primitive.Types.OffsetSize import Foundation.Internal.Proxy import Foundation.Collection import Foundation.Collection.Buildable (builderLift)
Foundation/Collection/Buildable.hs view
@@ -28,7 +28,7 @@ -- >>> import Control.Monad.ST -- >>> import Foundation.Array.Unboxed -- >>> import Foundation.Internal.Base--- >>> import Foundation.Internal.Types+-- >>> import Foundation.Primitive.OffsetSize  -- | Collections that can be built chunk by chunk. --
Foundation/Collection/Indexed.hs view
@@ -12,47 +12,49 @@     ) where  import           Foundation.Internal.Base+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Collection.Element import qualified Data.List import qualified Foundation.Array.Unboxed as UV import qualified Foundation.Array.Boxed as BA+import qualified Foundation.Array.Common as A import qualified Foundation.String.UTF8 as S  -- | Collection of elements that can indexed by int class IndexedCollection c where-    (!) :: c -> Int -> Maybe (Element c)-    findIndex :: (Element c -> Bool) -> c -> Maybe Int+    (!) :: c -> Offset (Element c) -> Maybe (Element c)+    findIndex :: (Element c -> Bool) -> c -> Maybe (Offset (Element c))  instance IndexedCollection [a] where-    (!) l n+    (!) l (Offset n)         | n < 0     = Nothing         | otherwise = case Data.List.drop n l of                         []  -> Nothing                         x:_ -> Just x-    findIndex = Data.List.findIndex+    findIndex predicate = fmap Offset . Data.List.findIndex predicate  instance UV.PrimType ty => IndexedCollection (UV.UArray ty) where     (!) l n-        | n < 0 || n >= UV.length l = Nothing-        | otherwise                 = Just $ UV.index l n+        | A.isOutOfBound n (UV.lengthSize l) = Nothing+        | otherwise                          = Just $ UV.index l n     findIndex predicate c = loop 0       where-        !len = UV.length c+        !len = UV.lengthSize c         loop i-            | i == len                       = Nothing+            | i .==# len                     = Nothing             | predicate (UV.unsafeIndex c i) = Just i             | otherwise                      = Nothing  instance IndexedCollection (BA.Array ty) where     (!) l n-        | n < 0 || n >= BA.length l = Nothing-        | otherwise                 = Just $ BA.index l n+        | A.isOutOfBound n (BA.lengthSize l) = Nothing+        | otherwise                          = Just $ BA.index l n     findIndex predicate c = loop 0       where-        !len = BA.length c+        !len = BA.lengthSize c         loop i-            | i == len  = Nothing-            | otherwise =+            | i .==# len = Nothing+            | otherwise  =                 if predicate (BA.unsafeIndex c i) then Just i else Nothing  instance IndexedCollection S.String where
Foundation/Collection/Mutable.hs view
@@ -10,8 +10,8 @@     ) where  import Foundation.Primitive.Monad+import Foundation.Primitive.Types.OffsetSize import Foundation.Internal.Base-import Foundation.Internal.Types  import qualified Foundation.Array.Unboxed.Mutable as MUV import qualified Foundation.Array.Unboxed as UV@@ -42,7 +42,7 @@  instance UV.PrimType ty => MutableCollection (MUV.MUArray ty) where     type MutableFreezed (MUV.MUArray ty) = UV.UArray ty-    type MutableKey (MUV.MUArray ty) = Int+    type MutableKey (MUV.MUArray ty) = Offset ty     type MutableValue (MUV.MUArray ty) = ty      thaw = UV.thaw@@ -59,7 +59,7 @@  instance MutableCollection (BA.MArray ty) where     type MutableFreezed (BA.MArray ty) = BA.Array ty-    type MutableKey (BA.MArray ty) = Int+    type MutableKey (BA.MArray ty) = Offset ty     type MutableValue (BA.MArray ty) = ty      thaw = BA.thaw
Foundation/Collection/Sequential.hs view
@@ -17,6 +17,7 @@     ) where  import           Foundation.Internal.Base+import           Foundation.Primitive.IntegralConv import           Foundation.Collection.Element import           Foundation.Collection.Collection import qualified Foundation.Collection.List as ListExtra@@ -35,6 +36,7 @@               , filter, reverse               , uncons, unsnoc, snoc, cons               , find, sortBy, singleton+              , replicate               #-}      -- | Take the first @n elements of a collection@@ -138,6 +140,9 @@     init :: NonEmpty c -> c     init nel = maybe (error "init") fst $ unsnoc (getNonEmpty nel) +    -- | Create a collection where the element in parameter is repeated N time+    replicate :: Word -> Element c -> c+     -- | Takes two collections and returns True iff the first collection is a prefix of the second.     isPrefixOf :: Eq (Element c) => c -> c -> Bool     default isPrefixOf :: Eq c => c -> c -> Bool@@ -185,6 +190,7 @@     find = Data.List.find     sortBy = Data.List.sortBy     singleton = (:[])+    replicate i = Data.List.replicate (wordToInt i)     isPrefixOf = Data.List.isPrefixOf     isSuffixOf = Data.List.isSuffixOf @@ -209,6 +215,7 @@     find = UV.find     sortBy = UV.sortBy     singleton = fromList . (:[])+    replicate = UV.replicate  instance Sequential (BA.Array ty) where     take = BA.take@@ -230,6 +237,7 @@     find = BA.find     sortBy = BA.sortBy     singleton = fromList . (:[])+    replicate = BA.replicate  instance Sequential S.String where     take = S.take@@ -252,3 +260,4 @@     find = S.find     sortBy = S.sortBy     singleton = S.singleton+    replicate = S.replicate
Foundation/Foreign/MemoryMap/Posix.hsc view
@@ -42,7 +42,7 @@     ) where  import Foundation.Internal.Base-import Foundation.Internal.Types+import Foundation.Primitive.Types.OffsetSize import System.Posix.Types import Foreign.Ptr import Foreign.C.Types
Foundation/Foreign/MemoryMap/Types.hs view
@@ -13,8 +13,8 @@  import GHC.Ptr import Foundation.Primitive.FinalPtr+import Foundation.Primitive.Types.OffsetSize import Foundation.Internal.Base-import Foundation.Internal.Types import Foundation.VFS (FilePath)  -- | Contains all the information related to a file mapping,
Foundation/Foreign/MemoryMap/Windows.hs view
@@ -7,8 +7,8 @@ import System.Win32.FileMapping import Control.Exception hiding (handle) -import Foundation.Internal.Types import Foundation.Internal.Base+import Foundation.Primitive.Types.OffsetSize import Foundation.Primitive.FinalPtr import Foundation.VFS import Foundation.Foreign.MemoryMap.Types
Foundation/Hashing/FNV.hs view
@@ -25,7 +25,7 @@  import           Foundation.Internal.Base import qualified Foundation.Array.Unboxed as A-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Primitive.Types import           Foundation.Numerical import           Foundation.Hashing.Hasher
Foundation/Hashing/SipHash.hs view
@@ -20,7 +20,7 @@  import           Data.Bits import           Foundation.Internal.Base-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Primitive.Types import           Foundation.Hashing.Hasher import qualified Foundation.Array.Unboxed as A
Foundation/IO/File.hs view
@@ -24,7 +24,7 @@ import qualified System.IO as S import           Foundation.Collection import           Foundation.VFS-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Internal.Base import           Foundation.String import           Foundation.Array@@ -137,16 +137,16 @@             r <- S.hGetBuf handle ptr blockSize             if r > 0 && r <= blockSize                 then do-                    (pos, validateRet) <- S.mutableValidate mv 0 r+                    (pos, validateRet) <- S.mutableValidate mv 0 (Size r)                     s <- case validateRet of-                        Nothing -> S.fromBytesUnsafe `fmap` V.freezeShrink mv r+                        Nothing -> S.fromBytesUnsafe `fmap` V.freezeShrink mv (Size r)                         Just S.MissingByte -> do-                            sRet <- S.fromBytesUnsafe `fmap` V.freezeShrink mv pos-                            V.unsafeSlide mv pos r+                            sRet <- S.fromBytesUnsafe `fmap` V.freezeShrink mv (pos - 0)+                            V.unsafeSlide mv pos (Offset r)                             return sRet                         Just _ ->                             error ("foldTextFile: invalid UTF8 sequence: byte position: " <> show (absPos + pos))-                    chunkf s acc >>= loop (absPos + r)+                    chunkf s acc >>= loop (absPos + Offset r)                 else error ("foldTextFile: read failed") -- FIXME  blockSize :: Int
Foundation/IO/FileMap.hs view
@@ -23,7 +23,7 @@     ) where  import           Control.Exception-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Internal.Base import           Foundation.VFS (FilePath) import           Foundation.Primitive.FinalPtr
Foundation/Internal/Environment.hs view
@@ -14,7 +14,7 @@     ) where  import           Foundation.Internal.Base-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import           System.IO.Unsafe          (unsafePerformIO)  #if MIN_VERSION_base(4,6,0)
Foundation/Internal/Natural.hs view
@@ -10,11 +10,14 @@  #else -import Prelude (Show,Eq,Ord,Enum,Num(..),Real(..),Integral(..),Integer,error,(<), (>), otherwise)+import Prelude (Show(..),Eq,Ord,Enum,Num(..),Real(..),Integral(..),Integer,error,(<), (>), otherwise) import Data.Typeable  newtype Natural = Natural Integer-    deriving (Show,Eq,Ord,Enum,Typeable)+    deriving (Eq,Ord,Enum,Typeable)++instance Show Natural where+    show (Natural i) = show i  -- re-create the buggy Num instance for Natural instance Num Natural where
− Foundation/Internal/Types.hs
@@ -1,117 +0,0 @@--- |--- Module      : Foundation.Internal.Types--- License     : BSD-style--- Maintainer  : Vincent Hanquez <vincent@snarc.org>--- Stability   : experimental--- Portability : portable----{-# LANGUAGE GeneralizedNewtypeDeriving #-}-module Foundation.Internal.Types-    ( FileSize(..)-    , Offset(..)-    , Offset8-    , offsetOfE-    , offsetPlusE-    , offsetMinusE-    , offsetRecast-    , (+.)-    , Size(..)-    , Size8-    , sizeOfE-    ) where--import GHC.Types-import GHC.Word-import Foundation.Internal.Base-import Foundation.Numerical.Primitives-import Foundation.Numerical.Number-import Foundation.Numerical.Additive-import Foundation.Numerical.Subtractive-import Foundation.Numerical.Multiplicative---- $setup--- >>> import Foundation.Array.Unboxed---- | File size in bytes-newtype FileSize = FileSize Word64-    deriving (Show,Eq,Ord)---- | Offset in bytes used for memory addressing (e.g. in a vector, string, ..)-type Offset8 = Offset Word8---- | Offset in a data structure consisting of elements of type 'ty'.------ Int is a terrible backing type which is hard to get away from,--- considering that GHC/Haskell are mostly using this for offset.--- Trying to bring some sanity by a lightweight wrapping.-newtype Offset ty = Offset Int-    deriving (Show,Eq,Ord,Enum)--instance Integral (Offset ty) where-    fromInteger n-        | n < 0     = error "Size: fromInteger: negative"-        | otherwise = Offset . fromInteger $ n-instance IsIntegral (Offset ty) where-    toInteger (Offset i) = toInteger i-instance IsNatural (Offset ty) where-    toNatural (Offset i) = toNatural (intToWord i)--instance Additive (Offset ty) where-    azero = Offset 0-    (+) (Offset a) (Offset b) = Offset (a+b)--instance Subtractive (Offset ty) where-    type Difference (Offset ty) = Size ty-    (Offset a) - (Offset b) = Size (a-b)--(+.) :: Offset ty -> Int -> Offset ty-(+.) (Offset a) b = Offset (a + b)--offsetOfE :: Size8 -> Offset ty -> Offset8-offsetOfE (Size sz) (Offset ty) = Offset (ty * sz)--offsetPlusE :: Offset ty -> Size ty -> Offset ty-offsetPlusE (Offset ofs) (Size sz) = Offset (ofs + sz)--offsetMinusE :: Offset ty -> Size ty -> Offset ty-offsetMinusE (Offset ofs) (Size sz) = Offset (ofs - sz)--offsetRecast :: Size8 -> Size8 -> Offset ty -> Offset ty2-offsetRecast szTy (Size szTy2) ofs =-    let (Offset bytes) = offsetOfE szTy ofs-     in Offset (bytes `div` szTy2)---- | Size of a data structure in bytes.-type Size8 = Size Word8--instance Integral (Size ty) where-    fromInteger n-        | n < 0     = error "Size: fromInteger: negative"-        | otherwise = Size . fromInteger $ n-instance IsIntegral (Size ty) where-    toInteger (Size i) = toInteger i-instance IsNatural (Size ty) where-    toNatural (Size i) = toNatural (intToWord i)--instance Additive (Size ty) where-    azero = Size 0-    (+) (Size a) (Size b) = Size (a+b)--instance Subtractive (Size ty) where-    type Difference (Size ty) = Size ty-    (Size a) - (Size b) = Size (a-b)---- | Size of a data structure.------ More specifically, it represents the number of elements of type `ty` that fit--- into the data structure.------ >>> lengthSize (fromList ['a', 'b', 'c', '🌟']) :: Size Char--- Size 4------ Same caveats as 'Offset' apply here.-newtype Size ty = Size Int-    deriving (Show,Eq,Ord,Enum)--sizeOfE :: Size8 -> Size ty -> Size8-sizeOfE (Size sz) (Size ty) = Size (ty * sz)
Foundation/Numerical/Subtractive.hs view
@@ -4,6 +4,7 @@  import           Foundation.Internal.Base import           Foundation.Internal.Natural+import           Foundation.Primitive.IntegralConv import qualified Prelude  -- | Represent class of things that can be subtracted.@@ -68,3 +69,6 @@ instance Subtractive Prelude.Double where     type Difference Prelude.Double = Prelude.Double     (-) = (Prelude.-)+instance Subtractive Prelude.Char where+    type Difference Prelude.Char = Prelude.Int+    (-) a b = (Prelude.-) (charToInt a) (charToInt b)
+ Foundation/Primitive/Floating.hs view
@@ -0,0 +1,21 @@+module Foundation.Primitive.Floating+    ( integerToDouble+    , naturalToDouble+    , doubleExponant+    ) where++import           GHC.Types+import           Foundation.Internal.Base+import           Foundation.Internal.Natural+import qualified Prelude (fromInteger, toInteger, (^^))++integerToDouble :: Integer -> Double+integerToDouble = Prelude.fromInteger+-- this depends on integer-gmp+--integerToDouble i = D# (doubleFromInteger i)++naturalToDouble :: Natural -> Double+naturalToDouble = integerToDouble . Prelude.toInteger++doubleExponant :: Double -> Int -> Double+doubleExponant = (Prelude.^^)
Foundation/Primitive/IntegralConv.hs view
@@ -13,6 +13,8 @@     , word64ToWord32s     , word64ToWord     , wordToChar+    , wordToInt+    , charToInt     ) where  #include "MachDeps.h"@@ -86,6 +88,11 @@ instance IntegralUpsize Int32 Integer where     integralUpsize = fromIntegral +instance IntegralUpsize Int Integer where+    integralUpsize = fromIntegral+instance IntegralUpsize Int Int64 where+    integralUpsize = intToInt64+ instance IntegralUpsize Int64 Integer where     integralUpsize = fromIntegral @@ -97,6 +104,14 @@     integralUpsize (W8# i) = wordToWord64 (W# i) instance IntegralUpsize Word8 Word where     integralUpsize (W8# i) = W# i+instance IntegralUpsize Word8 Int16 where+    integralUpsize (W8# w) = I16# (word2Int# w)+instance IntegralUpsize Word8 Int32 where+    integralUpsize (W8# w) = I32# (word2Int# w)+instance IntegralUpsize Word8 Int64 where+    integralUpsize (W8# w) = intToInt64 (I# (word2Int# w))+instance IntegralUpsize Word8 Int where+    integralUpsize (W8# w) = I# (word2Int# w) instance IntegralUpsize Word8 Integer where     integralUpsize = fromIntegral instance IntegralUpsize Word8 Natural where@@ -122,11 +137,21 @@ instance IntegralUpsize Word32 Natural where     integralUpsize = fromIntegral +instance IntegralUpsize Word Integer where+    integralUpsize = fromIntegral+instance IntegralUpsize Word Natural where+    integralUpsize = fromIntegral+instance IntegralUpsize Word Word64 where+    integralUpsize = wordToWord64+ instance IntegralUpsize Word64 Integer where     integralUpsize = fromIntegral instance IntegralUpsize Word64 Natural where     integralUpsize = fromIntegral +instance IntegralUpsize Natural Integer where+    integralUpsize = fromIntegral+ instance IntegralDownsize Int Int8 where     integralDownsize      (I# i) = I8# (narrow8Int# i)     integralDownsizeCheck = integralDownsizeBounded integralDownsize@@ -254,11 +279,17 @@  #if WORD_SIZE_IN_BITS == 64 word64ToWord32s :: Word64 -> (# Word32, Word32 #)-word64ToWord32s (W64# w) = (# W32# (uncheckedShiftRL# w 32#), W32# (narrow32Word# w) #)+word64ToWord32s (W64# w64) = (# W32# (uncheckedShiftRL# w64 32#), W32# (narrow32Word# w64) #) #else word64ToWord32s :: Word64 -> (# Word32, Word32 #)-word64ToWord32s (W64# w) = (# W32# (word64ToWord# (uncheckedShiftRL64# w 32#)), W32# (word64ToWord# w) #)+word64ToWord32s (W64# w64) = (# W32# (word64ToWord# (uncheckedShiftRL64# w64 32#)), W32# (word64ToWord# w64) #) #endif  wordToChar :: Word -> Char-wordToChar (W# w) = C# (chr# (word2Int# w))+wordToChar (W# word) = C# (chr# (word2Int# word))++wordToInt :: Word -> Int+wordToInt (W# word) = I# (word2Int# word)++charToInt :: Char -> Int+charToInt (C# x) = I# (ord# x)
Foundation/Primitive/Types.hs view
@@ -36,7 +36,7 @@ import           Foreign.C.Types import           Foundation.Internal.Proxy import           Foundation.Internal.Base-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Primitive.Endianness import           Foundation.Primitive.Monad import qualified Prelude (quot)
+ Foundation/Primitive/Types/OffsetSize.hs view
@@ -0,0 +1,142 @@+-- |+-- Module      : Foundation.Primitive.Types.OffsetSize+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : experimental+-- Portability : portable+--+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MagicHash #-}+module Foundation.Primitive.Types.OffsetSize+    ( FileSize(..)+    , Offset(..)+    , Offset8+    , offsetOfE+    , offsetPlusE+    , offsetMinusE+    , offsetRecast+    , offsetCast+    , sizeCast+    , sizeLastOffset+    , (+.)+    , (.==#)+    , Size(..)+    , Size8+    , sizeOfE+    ) where++import GHC.Types+import GHC.Word+import Foundation.Internal.Base+import Foundation.Internal.Proxy+import Foundation.Numerical.Primitives+import Foundation.Numerical.Number+import Foundation.Numerical.Additive+import Foundation.Numerical.Subtractive+import Foundation.Numerical.Multiplicative++-- $setup+-- >>> import Foundation.Array.Unboxed++-- | File size in bytes+newtype FileSize = FileSize Word64+    deriving (Show,Eq,Ord)++-- | Offset in bytes used for memory addressing (e.g. in a vector, string, ..)+type Offset8 = Offset Word8++-- | Offset in a data structure consisting of elements of type 'ty'.+--+-- Int is a terrible backing type which is hard to get away from,+-- considering that GHC/Haskell are mostly using this for offset.+-- Trying to bring some sanity by a lightweight wrapping.+newtype Offset ty = Offset Int+    deriving (Show,Eq,Ord,Enum)++instance Integral (Offset ty) where+    fromInteger n+        | n < 0     = error "Size: fromInteger: negative"+        | otherwise = Offset . fromInteger $ n+instance IsIntegral (Offset ty) where+    toInteger (Offset i) = toInteger i+instance IsNatural (Offset ty) where+    toNatural (Offset i) = toNatural (intToWord i)++instance Additive (Offset ty) where+    azero = Offset 0+    (+) (Offset a) (Offset b) = Offset (a+b)++instance Subtractive (Offset ty) where+    type Difference (Offset ty) = Size ty+    (Offset a) - (Offset b) = Size (a-b)++(+.) :: Offset ty -> Int -> Offset ty+(+.) (Offset a) b = Offset (a + b)++-- . is offset (as a pointer from a beginning), and # is the size (amount of data)+(.==#) :: Offset ty -> Size ty -> Bool+(.==#) (Offset ofs) (Size sz) = ofs == sz+{-# INLINE (.==#) #-}++offsetOfE :: Size8 -> Offset ty -> Offset8+offsetOfE (Size sz) (Offset ty) = Offset (ty * sz)++offsetPlusE :: Offset ty -> Size ty -> Offset ty+offsetPlusE (Offset ofs) (Size sz) = Offset (ofs + sz)++offsetMinusE :: Offset ty -> Size ty -> Offset ty+offsetMinusE (Offset ofs) (Size sz) = Offset (ofs - sz)++offsetRecast :: Size8 -> Size8 -> Offset ty -> Offset ty2+offsetRecast szTy (Size szTy2) ofs =+    let (Offset bytes) = offsetOfE szTy ofs+     in Offset (bytes `div` szTy2)++offsetCast :: Proxy (a -> b) -> Offset a -> Offset b+offsetCast _ (Offset o) = Offset o+{-# INLINE offsetCast #-}++sizeCast :: Proxy (a -> b) -> Size a -> Size b+sizeCast _ (Size sz) = Size sz+{-# INLINE sizeCast #-}++-- TODO add a callstack, or a construction to prevent size == 0 error+sizeLastOffset :: Size a -> Offset a+sizeLastOffset (Size s)+    | s > 0     = Offset (pred s)+    | otherwise = error "last offset on size 0"++-- | Size of a data structure in bytes.+type Size8 = Size Word8++instance Integral (Size ty) where+    fromInteger n+        | n < 0     = error "Size: fromInteger: negative"+        | otherwise = Size . fromInteger $ n+instance IsIntegral (Size ty) where+    toInteger (Size i) = toInteger i+instance IsNatural (Size ty) where+    toNatural (Size i) = toNatural (intToWord i)++instance Additive (Size ty) where+    azero = Size 0+    (+) (Size a) (Size b) = Size (a+b)++instance Subtractive (Size ty) where+    type Difference (Size ty) = Size ty+    (Size a) - (Size b) = Size (a-b)++-- | Size of a data structure.+--+-- More specifically, it represents the number of elements of type `ty` that fit+-- into the data structure.+--+-- >>> lengthSize (fromList ['a', 'b', 'c', '🌟']) :: Size Char+-- Size 4+--+-- Same caveats as 'Offset' apply here.+newtype Size ty = Size Int+    deriving (Show,Eq,Ord,Enum)++sizeOfE :: Size8 -> Size ty -> Size8+sizeOfE (Size sz) (Size ty) = Size (ty * sz)
Foundation/Primitive/Utils.hs view
@@ -17,7 +17,7 @@     ) where  import           Foundation.Internal.Base-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Internal.Primitive import           Foundation.Primitive.Monad import           GHC.Prim
Foundation/Random.hs view
@@ -28,7 +28,7 @@     ) where  import           Foundation.Internal.Base-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Internal.Proxy import           Foundation.Primitive.Monad import           Foundation.System.Entropy
Foundation/String/ASCII.hs view
@@ -37,7 +37,7 @@ import qualified Foundation.Array.Unboxed.Mutable   as MVec import qualified Foundation.Collection              as C import           Foundation.Internal.Base-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Numerical import           Foundation.Primitive.Monad import           Foundation.Foreign@@ -106,13 +106,14 @@     find = find     sortBy = sortBy     singleton = fromList . (:[])+    replicate n = fromList . C.replicate n  instance C.Zippable AsciiString where   -- TODO Use a string builder once available   zipWith f a b = sFromList (C.zipWith f a b)  next :: AsciiString -> Offset CUChar -> (# CUChar, Offset CUChar #)-next (AsciiString ba) (Offset n) = (# h, Offset (n + 1) #)+next (AsciiString ba) n = (# h, n + 1 #)   where     !h = Vec.unsafeIndex ba n @@ -209,7 +210,7 @@ length s = let (Size l) = size s in l  replicate :: Int -> CUChar -> AsciiString-replicate n c = AsciiString $ Vec.create n (const c)+replicate n c = AsciiString $ Vec.create (Size n) (const c)  -- | Copy the AsciiString copy :: AsciiString -> AsciiString
Foundation/String/Encoding/ASCII7.hs view
@@ -14,7 +14,7 @@     ) where  import Foundation.Internal.Base-import Foundation.Internal.Types+import Foundation.Primitive.Types.OffsetSize import Foundation.Numerical import Foundation.Primitive.Monad 
Foundation/String/Encoding/Encoding.hs view
@@ -14,7 +14,7 @@     ) where  import           Foundation.Internal.Base-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Primitive.Monad import           Foundation.Primitive.Types import           Foundation.Boot.Builder
Foundation/String/Encoding/ISO_8859_1.hs view
@@ -14,7 +14,7 @@     ) where  import Foundation.Internal.Base-import Foundation.Internal.Types+import Foundation.Primitive.Types.OffsetSize import Foundation.Numerical import Foundation.Primitive.Monad 
Foundation/String/Encoding/UTF16.hs view
@@ -12,7 +12,7 @@     ) where  import Foundation.Internal.Base-import Foundation.Internal.Types+import Foundation.Primitive.Types.OffsetSize import Foundation.Primitive.Monad import GHC.Prim import GHC.Word
Foundation/String/Encoding/UTF32.hs view
@@ -12,7 +12,7 @@     ) where  import Foundation.Internal.Base-import Foundation.Internal.Types+import Foundation.Primitive.Types.OffsetSize import Foundation.Primitive.Monad import GHC.Prim import GHC.Word
Foundation/String/ModifiedUTF8.hs view
@@ -25,7 +25,7 @@ import           Control.Monad (mapM_)  import           Foundation.Internal.Base-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import qualified Foundation.Array.Unboxed as Vec import           Foundation.Array.Unboxed (UArray) import           Foundation.Numerical
+ Foundation/String/Read.hs view
@@ -0,0 +1,8 @@+module Foundation.String.Read+    ( readInteger+    , readNatural+    , readDouble+    , readFloatingExact+    ) where++import Foundation.String.UTF8
Foundation/String/UTF8.hs view
@@ -66,6 +66,10 @@     , reverse     , builderAppend     , builderBuild+    , readInteger+    , readNatural+    , readDouble+    , readFloatingExact     -- * Legacy utility     , lines     , words@@ -77,12 +81,16 @@ import           Foundation.Array.Unboxed.ByteArray (MutableByteArray) import qualified Foundation.Array.Unboxed.Mutable   as MVec import           Foundation.Internal.Base+import           Foundation.Bits+import           Foundation.Internal.Natural import           Foundation.Internal.MonadTrans import           Foundation.Internal.Primitive-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import           Foundation.Numerical import           Foundation.Primitive.Monad import           Foundation.Primitive.Types+import           Foundation.Primitive.IntegralConv+import           Foundation.Primitive.Floating import           Foundation.Boot.Builder import qualified Foundation.Boot.List as List import           Foundation.String.UTF8Table@@ -212,13 +220,13 @@ -- | Similar to 'validate' but works on a 'MutableByteArray' mutableValidate :: PrimMonad prim                 => MutableByteArray (PrimState prim)-                -> Int-                -> Int-                -> prim (Int, Maybe ValidationFailure)+                -> Offset Word8+                -> Size Word8+                -> prim (Offset Word8, Maybe ValidationFailure) mutableValidate mba ofsStart sz = do     loop ofsStart   where-    end = ofsStart + sz+    end = ofsStart `offsetPlusE` sz      loop ofs         | ofs > end  = error "mutableValidate: internal error: went pass offset"@@ -234,7 +242,7 @@         let nbConts = getNbBytes h         if nbConts == 0xff             then return (pos, Just InvalidHeader)-            else if pos + 1 + nbConts > end+            else if pos + 1 + Offset nbConts > end                 then return (pos, Just MissingByte)                 else do                     case nbConts of@@ -342,16 +350,24 @@     toContinuation :: Word# -> Word#     toContinuation w = or# (and# w 0x3f##) 0x80## +-- A variant of 'next' when you want the next character+-- to be ASCII only. if Bool is False, then it's not ascii,+-- otherwise it is and the return Word8 is valid.+nextAscii :: String -> Offset8 -> (# Word8, Bool #)+nextAscii (String ba) n = (# w, not (testBit w 7) #)+  where+    !w = Vec.unsafeIndex ba n+ next :: String -> Offset8 -> (# Char, Offset8 #)-next (String ba) (Offset n) =+next (String ba) n =     case getNbBytes# h of-        0# -> (# toChar h, Offset $ n + 1 #)-        1# -> (# toChar (decode2 (Vec.unsafeIndex ba (n + 1))) , Offset $ n + 2 #)+        0# -> (# toChar h, n + 1 #)+        1# -> (# toChar (decode2 (Vec.unsafeIndex ba (n + 1))) , n + 2 #)         2# -> (# toChar (decode3 (Vec.unsafeIndex ba (n + 1))-                                 (Vec.unsafeIndex ba (n + 2))) , Offset $ n + 3 #)+                                 (Vec.unsafeIndex ba (n + 2))) , n + 3 #)         3# -> (# toChar (decode4 (Vec.unsafeIndex ba (n + 1))                                  (Vec.unsafeIndex ba (n + 2))-                                 (Vec.unsafeIndex ba (n + 3))) , Offset $ n + 4 #)+                                 (Vec.unsafeIndex ba (n + 3))) , n + 4 #)         r -> error ("next: internal error: invalid input: offset=" <> show n <> " table=" <> show (I# r) <> " h=" <> show (W# h))   where     !(W8# h) = Vec.unsafeIndex ba n@@ -423,16 +439,16 @@ numBytes UTF8_4{} = Size 4  writeUTF8Char :: PrimMonad prim => MutableString (PrimState prim) -> Offset8 -> UTF8Char -> prim ()-writeUTF8Char (MutableString mba) (Offset i) (UTF8_1 x1) =+writeUTF8Char (MutableString mba) i (UTF8_1 x1) =     Vec.unsafeWrite mba i     x1-writeUTF8Char (MutableString mba) (Offset i) (UTF8_2 x1 x2) = do+writeUTF8Char (MutableString mba) i (UTF8_2 x1 x2) = do     Vec.unsafeWrite mba i     x1     Vec.unsafeWrite mba (i+1) x2-writeUTF8Char (MutableString mba) (Offset i) (UTF8_3 x1 x2 x3) = do+writeUTF8Char (MutableString mba) i (UTF8_3 x1 x2 x3) = do     Vec.unsafeWrite mba i     x1     Vec.unsafeWrite mba (i+1) x2     Vec.unsafeWrite mba (i+2) x3-writeUTF8Char (MutableString mba) (Offset i) (UTF8_4 x1 x2 x3 x4) = do+writeUTF8Char (MutableString mba) i (UTF8_4 x1 x2 x3 x4) = do     Vec.unsafeWrite mba i     x1     Vec.unsafeWrite mba (i+1) x2     Vec.unsafeWrite mba (i+2) x3@@ -440,7 +456,7 @@ {-# INLINE writeUTF8Char #-}  write :: PrimMonad prim => MutableString (PrimState prim) -> Offset8 -> Char -> prim Offset8-write (MutableString mba) (Offset i) c =+write (MutableString mba) i c =     if      bool# (ltWord# x 0x80##   ) then encode1     else if bool# (ltWord# x 0x800##  ) then encode2     else if bool# (ltWord# x 0x10000##) then encode3@@ -449,14 +465,14 @@     !(I# xi) = fromEnum c     !x       = int2Word# xi -    encode1 = Vec.unsafeWrite mba i (W8# x) >> return (Offset $ i + 1)+    encode1 = Vec.unsafeWrite mba i (W8# x) >> return (i + 1)      encode2 = do         let x1  = or# (uncheckedShiftRL# x 6#) 0xc0##             x2  = toContinuation x         Vec.unsafeWrite mba i     (W8# x1)         Vec.unsafeWrite mba (i+1) (W8# x2)-        return $ Offset (i + 2)+        return (i + 2)      encode3 = do         let x1  = or# (uncheckedShiftRL# x 12#) 0xe0##@@ -465,7 +481,7 @@         Vec.unsafeWrite mba i     (W8# x1)         Vec.unsafeWrite mba (i+1) (W8# x2)         Vec.unsafeWrite mba (i+2) (W8# x3)-        return $ Offset (i + 3)+        return (i + 3)      encode4 = do         let x1  = or# (uncheckedShiftRL# x 18#) 0xf0##@@ -476,7 +492,7 @@         Vec.unsafeWrite mba (i+1) (W8# x2)         Vec.unsafeWrite mba (i+2) (W8# x3)         Vec.unsafeWrite mba (i+3) (W8# x4)-        return $ Offset (i + 4)+        return (i + 4)      toContinuation :: Word# -> Word#     toContinuation w = or# (and# w 0x3f##) 0x80##@@ -544,14 +560,14 @@ take n s@(String ba)     | n <= 0           = mempty     | n >= C.length ba = s-    | otherwise        = let (Offset o) = indexN n s in String $ Vec.take o ba+    | otherwise        = let (Offset o) = indexN (Offset n) s in String $ Vec.take o ba  -- | Create a string with the remaining Chars after dropping @n Chars from the beginning drop :: Int -> String -> String drop n s@(String ba)     | n <= 0           = s     | n >= C.length ba = mempty-    | otherwise        = let (Offset o) = indexN n s in String $ Vec.drop o ba+    | otherwise        = let (Offset o) = indexN (Offset n) s in String $ Vec.drop o ba  -- | Split a string at the Offset specified (in Char) returning both -- the leading part and the remaining part.@@ -560,25 +576,21 @@     | nI <= 0           = (mempty, s)     | nI >= C.length ba = (s, mempty)     | otherwise =-        let (Offset k) = indexN nI s+        let (Offset k) = indexN (Offset nI) s             (v1,v2)    = C.splitAt k ba          in (String v1, String v2)  -- | Return the offset (in bytes) of the N'th sequence in an UTF8 String-indexN :: Int -> String -> Offset Word8-indexN nI (String ba) = Vec.unsafeDewrap goVec goAddr ba+indexN :: Offset Char -> String -> Offset Word8+indexN !n (String ba) = Vec.unsafeDewrap goVec goAddr ba   where-    !n = Size nI-    end :: Offset Char-    !end = Offset 0 `offsetPlusE` n-     goVec :: ByteArray# -> Offset Word8 -> Offset Word8     goVec !ma !start = loop start (Offset 0)       where         !len = start `offsetPlusE` Vec.lengthSize ba         loop :: Offset Word8 -> Offset Char -> Offset Word8         loop !idx !i-            | idx >= len || i >= end = sizeAsOffset (idx - start)+            | idx >= len || i >= n = sizeAsOffset (idx - start)             | otherwise              = loop (idx `offsetPlusE` d) (i + Offset 1)           where d = skipNextHeaderValue (primBaIndex ma idx)     {-# INLINE goVec #-}@@ -589,8 +601,8 @@         !len = start `offsetPlusE` Vec.lengthSize ba         loop :: Offset Word8 -> Offset Char -> Offset Word8         loop !idx !i-            | idx >= len || i >= end = sizeAsOffset (idx - start)-            | otherwise              = loop (idx `offsetPlusE` d) (i + Offset 1)+            | idx >= len || i >= n = sizeAsOffset (idx - start)+            | otherwise            = loop (idx `offsetPlusE` d) (i + Offset 1)           where d = skipNextHeaderValue (primAddrIndex ptr idx)     {-# INLINE goAddr #-} {-# INLINE indexN #-}@@ -641,7 +653,7 @@ -- This is unsafe considering that one can create a substring -- starting and/or ending on the middle of a UTF8 sequence. sub :: String -> Offset8 -> Offset8 -> String-sub (String ba) (Offset start) (Offset end) = String $ Vec.sub ba start end+sub (String ba) start end = String $ Vec.sub ba start end  -- | Internal call to split at a given index in offset of bytes. --@@ -807,18 +819,18 @@ length s = let (Size sz) = lengthSize s in sz  -- | Replicate a character @c@ @n@ times to create a string of length @n@-replicate :: Int -> Char -> String+replicate :: Word -> Char -> String replicate n c = runST (new nbBytes >>= fill)   where-    end       = azero `offsetPlusE` nbBytes-    nbBytes   = Size $ sz * n-    (Size sz) = charToBytes (fromEnum c)+    --end       = azero `offsetPlusE` nbBytes+    nbBytes   = scale n sz+    sz = charToBytes (fromEnum c)     fill :: PrimMonad prim => MutableString (PrimState prim) -> prim String     fill ms = loop (Offset 0)       where         loop idx-            | idx == end = freeze ms-            | otherwise  = write ms idx c >>= loop+            | idx .==# nbBytes = freeze ms+            | otherwise        = write ms idx c >>= loop  -- | Copy the String --@@ -955,7 +967,7 @@ unsnoc :: String -> Maybe (String, Char) unsnoc s     | null s    = Nothing-    | otherwise = case index s (length s - 1) of+    | otherwise = case index s (sizeLastOffset $ lengthSize s) of         Nothing -> Nothing         Just c  -> Just (revDrop 1 s, c) @@ -1000,14 +1012,14 @@     !len = size s     -- write those bytes     loop :: PrimMonad prim => MutableString (PrimState prim) -> Offset8 -> Offset8 -> prim String-    loop ms@(MutableString mba) sidx@(Offset si) didx+    loop ms@(MutableString mba) si didx         | didx == Offset 0 = freeze ms         | otherwise = do             let !h = Vec.unsafeIndex ba si                 !nb = Size (getNbBytes h + 1)-                didx'@(Offset d) = didx `offsetMinusE` nb+                d  = didx `offsetMinusE` nb             case nb of-                Size 1 -> Vec.unsafeWrite mba d      h+                Size 1 -> Vec.unsafeWrite mba d h                 Size 2 -> do                     Vec.unsafeWrite mba d       h                     Vec.unsafeWrite mba (d + 1) (Vec.unsafeIndex ba (si + 1))@@ -1021,13 +1033,13 @@                     Vec.unsafeWrite mba (d + 2) (Vec.unsafeIndex ba (si + 2))                     Vec.unsafeWrite mba (d + 3) (Vec.unsafeIndex ba (si + 3))                 _  -> return () -- impossible-            loop ms (sidx `offsetPlusE` nb) didx'+            loop ms (si `offsetPlusE` nb) d  -- | Return the nth character in a String -- -- Compared to an array, the string need to be scanned from the beginning -- since the UTF8 encoding is variable.-index :: String -> Int -> Maybe Char+index :: String -> Offset Char -> Maybe Char index s n     | ofs >= end = Nothing     | otherwise  =@@ -1041,18 +1053,17 @@ -- | Return the index in unit of Char of the first occurence of the predicate returning True -- -- If not found, Nothing is returned-findIndex :: (Char -> Bool) -> String -> Maybe Int-findIndex predicate s = loop (Offset 0)+findIndex :: (Char -> Bool) -> String -> Maybe (Offset Char)+findIndex predicate s = loop 0 0   where     !sz = size s-    end = Offset 0 `offsetPlusE` sz-    loop idx-        | idx == end = Nothing-        | otherwise =+    loop ofs idx+        | idx .==# sz = Nothing+        | otherwise   =             let (# c, idx' #) = next s idx              in case predicate c of-                    True  -> let (Offset r) = idx in Just r-                    False -> loop idx'+                    True  -> Just ofs+                    False -> loop (ofs+1) idx'  -- | Various String Encoding that can be use to convert to and from bytes data Encoding@@ -1238,3 +1249,185 @@         let sz = Vec.lengthSize x         Vec.unsafeCopyAtRO mba (sizeAsOffset (end - sz)) x (Offset 0) sz         fillFromEnd (end - sz) xs mba++-- | Read an Integer from a String+--+-- Consume an optional minus sign and many digits until end of string.+readInteger :: String -> Maybe Integer+readInteger str+    | sz == 0  = Nothing+    | otherwise =+         let (# modF, startOfs #) = case nextAscii str 0 of+                                        -- '-'+                                        (# 0x2d, True #) -> (# negate , 1 #)+                                        _                -> (# id, 0 #)+          in case decimalDigits 0 str startOfs of+                (# acc, True, endOfs #) | endOfs > startOfs -> Just $ modF acc+                _                                           -> Nothing+  where+    !sz = size str++-- | Read a Natural from a String+--+-- Consume many digits until end of string.+readNatural :: String -> Maybe Natural+readNatural str+    | sz == 0  = Nothing+    | otherwise =+        case decimalDigits 0 str 0 of+            (# acc, True, endOfs #) | endOfs > 0 -> Just $ acc+            _                                    -> Nothing+  where+    !sz = size str++-- | Try to read a Double+readDouble :: String -> Maybe Double+readDouble s =+    readFloatingExact s $ \isNegative integral mFloating mExponant ->+        case (mFloating, mExponant) of+            (Nothing, Nothing)             -> Just $ applySign isNegative $                         naturalToDouble integral+            (Nothing, Just exponant)       -> Just $ applySign isNegative $ withExponant exponant $ naturalToDouble integral+            (Just floating, Nothing)       -> Just $ applySign isNegative $                         (naturalToDouble integral + floatingToDouble floating)+            (Just floating, Just exponant) -> Just $ applySign isNegative $ withExponant exponant $ (naturalToDouble integral + floatingToDouble floating)+  where+    applySign True = negate+    applySign False = id+    withExponant e v = v * doubleExponant 10 e+    floatingToDouble (digits, n) = naturalToDouble n / (10 ^ digits)++type ReadFloatingCallback a = Bool                  -- sign+                           -> Natural               -- integral part+                           -> Maybe (Word, Natural) -- optional number of zero and number representing floating part+                           -> Maybe Int             -- optional integer representing exponent in base 10+                           -> Maybe a++-- | Read an Floating like number of the form:+--+--   [ '-' ] <numbers> [ '.' <numbers> ] [ ( 'e' | 'E' ) [ '-' ] <number> ]+--+-- Call a function with:+--+-- * A boolean representing if the number is negative+-- * The leading integral part+-- * The floating part (number of digits after fractional part, and number) if any+-- * The exponant if any+--+-- The code is structured as a simple state machine that:+--+-- * Optionally Consume a '-' sign+-- * Consume number for the integral part+-- * Optionally+--   * Consume '.'+--   * Consume leading zeros explicitely to gather scale of the fractional part+--   * Consume remaining digits if not already end of string+-- * Optionally Consume a 'e' or 'E' follow by an optional '-' and a number+--+readFloatingExact :: String -> ReadFloatingCallback a -> Maybe a+readFloatingExact str f+    | sz == 0   = Nothing+    | otherwise =+        -- try to eat a '-', otherwise call consumeIntegral+        case nextAscii str 0 of+            (# _   , False #) -> Nothing+            (# 0x2d, True #)  -> consumeIntegral True 1+            _                 -> consumeIntegral False 0+  where+    !sz = size str++    consumeIntegral isNegative startOfs =+        case decimalDigits 0 str startOfs of+            (# acc, True , endOfs #) | endOfs > startOfs -> f isNegative acc Nothing Nothing -- end of stream and no '.'+            (# acc, False, endOfs #) | endOfs > startOfs -> consumeDot isNegative acc endOfs+            _                                            -> Nothing++    -- this is not the end of the stream since otherwise consumeIntegral would have+    -- returned already+    -- try either to consume '.' or pass state to consumeExponant+    consumeDot isNegative integral startOfs =+        case nextAscii str startOfs of+            (# _   , False #) -> Nothing+            (# 0x2e, True #)  -> consumeZero isNegative integral (startOfs + 1)+            (# _   , True #)  -> consumeExponant isNegative integral Nothing startOfs++    consumeZero isNegative integral startOfs = loop 0 startOfs+      where+        loop nbDigits ofs+            | ofs .==# sz = if nbDigits == 0 then Nothing else f isNegative integral (Just (nbDigits, 0)) Nothing+            | otherwise   =+                case nextAscii str ofs of+                    (# _   , False #) -> Nothing+                    (# 0x30, True #)  -> loop (nbDigits+1) (ofs+1)+                    (# c   , True #)+                        | c == 0x45 || c == 0x65 -> if nbDigits > 0 then consumeExponant isNegative integral (Just (nbDigits, 0)) ofs else Nothing+                        | otherwise              -> consumeFloat isNegative integral nbDigits ofs++    consumeFloat isNegative integral nbDigits startOfs =+        case decimalDigits 0 str startOfs of+            (# acc, True, endOfs #) | endOfs > startOfs -> let (Size !diff) = endOfs - startOfs+                                                            in f isNegative integral (Just (nbDigits+integralCast diff, acc)) Nothing+            (# acc, False, endOfs #) | endOfs > startOfs -> let (Size !diff) = endOfs - startOfs+                                                            in consumeExponant isNegative integral (Just (nbDigits+integralCast diff, acc)) endOfs+            _                                           -> Nothing++    consumeExponant !isNegative !integral !floating !startOfs+        | startOfs .==# sz = f isNegative integral floating Nothing+        | otherwise        =+            -- consume 'E' or 'e'+            case nextAscii str startOfs of+                (# _   , False #) -> Nothing -- more character but no ascii+                (# 0x45, True  #) -> consumeExponantSign (startOfs+1)+                (# 0x65, True  #) -> consumeExponantSign (startOfs+1)+                (# _   , True  #) -> Nothing+      where+        consumeExponantSign ofs+            | ofs .==# sz = Nothing+            | otherwise   =+                case nextAscii str ofs of+                    (# _   , False #) -> Nothing+                    (# 0x2d, True  #) -> consumeExponantNumber negate (ofs+1)+                    (# _   , True  #) -> consumeExponantNumber id     ofs+        consumeExponantNumber signFct ofs =+            case decimalDigits 0 str ofs of+                (# acc, True, endOfs #) | endOfs > ofs -> f isNegative integral floating (Just $ signFct acc)+                _                                      -> Nothing++-- | Take decimal digits and accumulate it in `acc`+--+-- The loop starts at the offset specified and finish either when:+--+-- * It reach the end of the string+-- * It reach a non-ASCII character+-- * It reach an ASCII character that is not a digit (0 to 9)+--+-- Otherwise each iterations:+--+-- * Transform the ASCII digits into a number+-- * scale the accumulator by 10+-- * Add the number (between 0 and 9) to the accumulator+--+-- It then returns:+--+-- * The new accumulated value+-- * Whether it stop by end of string or not+-- * The end offset when the loop stopped+--+-- If end offset == start offset then no digits have been consumed by+-- this function+decimalDigits :: (IntegralUpsize Word8 acc, Additive acc)+              => acc+              -> String+              -> Offset Word8+              -> (# acc, Bool, Offset Word8 #)+decimalDigits startAcc str startOfs = loop startAcc startOfs+  where+    !sz = size str+    loop acc ofs+        | ofs .==# sz = (# acc, True, ofs #)+        | otherwise   =+            case nextAscii str ofs of+                (# d, True #) | isDigit d -> loop (scale (10::Word) acc + fromDigit d) (ofs+1)+                (# _, _ #)                -> (# acc, False, ofs #)+    ascii0 = 0x30 -- use pattern synonym when we support >= 8.0+    ascii9 = 0x39+    isDigit c = c >= ascii0 && c <= ascii9+    fromDigit c = integralUpsize (c - ascii0)
Foundation/System/Entropy.hs view
@@ -12,7 +12,7 @@   import           Foundation.Internal.Base-import           Foundation.Internal.Types+import           Foundation.Primitive.Types.OffsetSize import qualified Foundation.Array.Unboxed.Mutable as A import qualified Foundation.Array.Unboxed as A import           Control.Exception
README.md view
@@ -132,3 +132,15 @@   Foundation uses and abuses type families.+++Code Organisation+=================++Every foundation modules start by `Foundation`.++* `Foundation` is the prelude replacement module.+* `Foundation.Internal` contains only compatibilty and re-export from ghc/ghc-prim/base.+* `Foundation.Primitive` is where all the lowlevel magic happens:+  * Important types that underpins many others part+  * Pervasive features
foundation.cabal view
@@ -1,5 +1,5 @@ Name:                foundation-Version:             0.0.6+Version:             0.0.7 Synopsis:            Alternative prelude with batteries and no dependencies Description:     A custom prelude with no dependencies apart from base.@@ -38,6 +38,11 @@   type: git   location: https://github.com/haskell-foundation/foundation +Flag experimental+  Description:       Enable building experimental features, known as highly unstable or without good support cross-platform+  Default:           False+  Manual:            False+ Flag bench-all   Description:       Add some comparaison benchmarks against other haskell libraries   Default:           False@@ -60,6 +65,7 @@                      Foundation.Convertible                      Foundation.String                      Foundation.String.ASCII+                     Foundation.String.Read                      Foundation.IO                      Foundation.IO.FileMap                      Foundation.VFS@@ -76,7 +82,6 @@                      Foundation.Monad.State                      Foundation.Network.IPv4                      Foundation.Network.IPv6-                     Foundation.Network.HostName                      Foundation.System.Info                      Foundation.Strict                      Foundation.Parser@@ -127,7 +132,6 @@                      Foundation.Internal.IsList                      Foundation.Internal.Identity                      Foundation.Internal.Proxy-                     Foundation.Internal.Types                      Foundation.Internal.PrimTypes                      Foundation.Internal.MonadTrans                      Foundation.Internal.Natural@@ -143,9 +147,11 @@                      Foundation.Primitive.Base16                      Foundation.Primitive.Endianness                      Foundation.Primitive.Types+                     Foundation.Primitive.Types.OffsetSize                      Foundation.Primitive.Monad                      Foundation.Primitive.Utils                      Foundation.Primitive.IntegralConv+                     Foundation.Primitive.Floating                      Foundation.Primitive.FinalPtr                      Foundation.Monad.MonadIO                      Foundation.Monad.Exception@@ -169,6 +175,8 @@   C-sources:         cbits/foundation_random.c                      cbits/foundation_network.c +  if flag(experimental)+    Exposed-modules: Foundation.Network.HostName   if os(windows)     Exposed-modules: Foundation.System.Bindings.Windows     Other-modules:   Foundation.Foreign.MemoryMap.Windows
tests/Checks.hs view
@@ -2,9 +2,13 @@ module Main where  import Foundation+import Foundation.Primitive import Foundation.Check+import Foundation.String.Read+import Foundation.Numerical+import qualified Prelude -testAdditive :: forall a . (Eq a, Additive a, Arbitrary a) => Proxy a -> Test+testAdditive :: forall a . (Show a, Eq a, Additive a, Arbitrary a) => Proxy a -> Test testAdditive _ = Group "Additive"     [ Property "eq"             $ azero === (azero :: a)     , Property "a + azero == a" $ \(v :: a)     -> v + azero === v@@ -12,6 +16,18 @@     , Property "a + b == b + a" $ \(v1 :: a) v2 -> v1 + v2 === v2 + v1     ] +readFloatingExact' :: String -> Maybe (Bool, Natural, Maybe (Word, Natural), Maybe Int)+readFloatingExact' s = readFloatingExact s (\s x y z -> Just (s,x,y,z))++doubleEqualApprox :: Double -> Double -> PropertyCheck+doubleEqualApprox d1 d2 = (propertyCompare pName1 (<) (negate lim) d) `propertyAnd` (propertyCompare pName2 (<) d lim)+  where +        d = d2 - d1++        pName1 = show (negate lim) <> " < " <> show d2 <> " - " <> show d1 <> " (== " <> show d <> " )"+        pName2 = show d1 <> " - " <> show d2 <> " (== " <> show d <> " )" <> " < " <> show lim+        lim = 1.0e-8+ main = defaultMain $ Group "foundation"     [ Group "Numerical"         [ Group "Int"@@ -20,10 +36,38 @@         , Group "Word64"             [ testAdditive (Proxy :: Proxy Word64)             ]-{--        , Group "Natural"-            [ testAdditive (Proxy :: Proxy Natural)+        ]+    , Group "String"+        [ Group "reading"+            [ Group "integer"+                [ Property "empty"         $ readInteger "" === Nothing+                , Property "just-sign"     $ readInteger "-" === Nothing+                , Property "extra-content" $ readInteger "-123a" === Nothing+                , Property "any"           $ \i -> readInteger (show i) === Just i+                ]+            , Group "floating-exact"+                [ Property "empty"         $ readFloatingExact' "" === Nothing+                , Property "just-sign"     $ readFloatingExact' "-" === Nothing+                , Property "extra-content" $ readFloatingExact' "-123a" === Nothing+                , Property "no-dot-after"  $ readFloatingExact' "-123." === Nothing+                , Property "case1"         $ readFloatingExact' "-123.1" === Just (True, 123, Just (1, 1), Nothing)+                , Property "case2"         $ readFloatingExact' "10001.001" === Just (False, 10001, Just (3, 1), Nothing)+                , Property "any"           $ \s i (v :: Word8) n ->+                                                let vw = integralUpsize v :: Word+                                                    sfloat = show n+                                                    digits = integralCast (length sfloat) + vw+                                                 in readFloatingExact' ((if s then "-" else "") <> show i <> "." <> replicate vw '0' <> sfloat) === Just (s, i, Just (digits, n), Nothing)+                ]+            , Group "Double"+                [ Property "case1" $ readDouble "96152.5" === Just 96152.5+                , Property "case2" $ maybe (propertyFail "Nothing") (doubleEqualApprox 1.2300000000000002e102) $ readDouble "1.2300000000000002e102"+                , Property "case3" $ maybe (propertyFail "Nothing") (doubleEqualApprox 0.00001204) $ readDouble "0.00001204"+                , Property "case4" $ maybe (propertyFail "Nothing") (doubleEqualApprox 2.5e12) $ readDouble "2.5e12"+                , Property "case5" $ maybe (propertyFail "Nothing") (doubleEqualApprox 6.0e-4) $ readDouble "6.0e-4"+                , Property "Prelude.read" $ \(d :: Double) -> case readDouble (show d) of+                                                                  Nothing -> propertyFail "Nothing"+                                                                  Just d' -> d' `doubleEqualApprox` (Prelude.read $ toList $ show d)+                ]             ]--}         ]     ]
tests/Imports.hs view
@@ -26,6 +26,7 @@ import Test.Tasty.HUnit        as X hiding (testCase, assert, assertFailure) import Test.QuickCheck.Monadic as X + import qualified Test.Tasty            as Y import qualified Test.Tasty.QuickCheck as Y import qualified Test.Tasty.HUnit      as Y
tests/Test/Foundation/Random.hs view
@@ -71,7 +71,7 @@  -- | Append random data to the test state randomTestAppend :: RandomTestState s -> UArray Word8 -> ST s ()-randomTestAppend (RandomTestState buckets) = mapM_ (addVec 1 . fromIntegral) . toList+randomTestAppend (RandomTestState buckets) = mapM_ (addVec 1 . Offset . fromIntegral) . toList   where     addVec a i = mutRead buckets i >>= \d -> mutWrite buckets i $! d+a 
tests/Test/Foundation/String.hs view
@@ -10,7 +10,6 @@ import Foundation import Foundation.String import Foundation.String.ASCII (AsciiString)-import Foundation.Collection  import Test.Tasty import Test.Tasty.QuickCheck
tests/Tests.hs view
@@ -142,10 +142,10 @@                   => Proxy a -> Proxy b -> Proxy col -> Gen (Element a) -> Gen (Element b) -> [TestTree] testBoxedZippable proxyA proxyB proxyCol genElementA genElementB =     [ testProperty "zip" $ withList2 $ \(as, bs) ->-        toListP proxyCol (zip (fromListP proxyA as) (fromListP proxyB bs)) == zip as bs+        toListP proxyCol (zip (fromListP proxyA as) (fromListP proxyB bs)) === zip as bs     , testProperty "zip . unzip == id" $ withListOfTuples $ \xs ->         let (as, bs) = unzip (fromListP proxyCol xs)-        in toListP proxyCol (zip (as `asProxyTypeOf` proxyA) (bs `asProxyTypeOf` proxyB)) == xs+        in toListP proxyCol (zip (as `asProxyTypeOf` proxyA) (bs `asProxyTypeOf` proxyB)) === xs     ]   where     withList2 = forAll ((,) <$> generateListOfElement genElementA <*> generateListOfElement genElementB)@@ -157,7 +157,7 @@ testZippable proxyA proxyB proxyCol genElementA genElementB genElementCol =     [ testProperty "zipWith" $ withList2AndE $ \(as, bs, c) ->         toListP proxyCol (zipWith (const (const c)) (fromListP proxyA as) (fromListP proxyB bs)-            ) == Prelude.replicate (Prelude.min (length as) (length bs)) c+            ) === Prelude.replicate (Prelude.min (length as) (length bs)) c     ]   where     withList2AndE = forAll ( (,,) <$> generateListOfElement genElementA <*> generateListOfElement genElementB@@ -167,43 +167,43 @@                   => Proxy a -> Proxy b -> Gen (Element a) -> Gen (Element b) -> [TestTree] testZippableProps proxyA proxyB genElementA genElementB =     [ testProperty "zipWith _|_ [] xs == []" $ withList $ \as ->-        toListP proxyA (zipWith undefined [] (fromListP proxyA as)) == []+        toListP proxyA (zipWith undefined [] (fromListP proxyA as)) === []     , testProperty "zipWith f a b == zipWith (flip f) b a" $ withList2 $ \(as, bs) ->         let f = ignore1             as' = fromListP proxyA as             bs' = fromListP proxyB bs         in toListP proxyB (zipWith f as' bs')-            == toListP proxyB (zipWith (flip f) bs' as')+            === toListP proxyB (zipWith (flip f) bs' as')     , testProperty "zipWith3 f [...] xs == zipWith id (zipWith f [...]) xs)" $ withList2 $ \(as, bs) ->         let f = ignore2             as' = fromListP proxyA as             bs' = fromListP proxyB bs         in toListP proxyB (zipWith3 f as' as' bs')-            == Prelude.zipWith id (zipWith f as as) bs+            === Prelude.zipWith id (zipWith f as as) bs     , testProperty "zipWith4 f [...] xs == zipWith id (zipWith3 f [...]) xs)" $ withList2 $ \(as, bs) ->         let f = ignore3             as' = fromListP proxyA as             bs' = fromListP proxyB bs         in toListP proxyB (zipWith4 f as' as' as' bs')-            == Prelude.zipWith id (zipWith3 f as as as) bs+            === Prelude.zipWith id (zipWith3 f as as as) bs     , testProperty "zipWith5 f [...] xs == zipWith id (zipWith4 f [...]) xs)" $ withList2 $ \(as, bs) ->         let f = ignore4             as' = fromListP proxyA as             bs' = fromListP proxyB bs         in toListP proxyB (zipWith5 f as' as' as' as' bs')-            == Prelude.zipWith id (zipWith4 f as as as as) bs+            === Prelude.zipWith id (zipWith4 f as as as as) bs     , testProperty "zipWith6 f [...] xs == zipWith id (zipWith5 f [...]) xs)" $ withList2 $ \(as, bs) ->         let f = ignore5             as' = fromListP proxyA as             bs' = fromListP proxyB bs         in toListP proxyB (zipWith6 f as' as' as' as' as' bs')-            == Prelude.zipWith id (zipWith5 f as as as as as) bs+            === Prelude.zipWith id (zipWith5 f as as as as as) bs     , testProperty "zipWith7 f [...] xs == zipWith id (zipWith6 f [...]) xs)" $ withList2 $ \(as, bs) ->         let f = ignore6             as' = fromListP proxyA as             bs' = fromListP proxyB bs         in toListP proxyB (zipWith7 f as' as' as' as' as' as' bs')-            == Prelude.zipWith id (zipWith6 f as as as as as as) bs+            === Prelude.zipWith id (zipWith6 f as as as as as as) bs     ]   where     -- ignore the first n arguments