packages feed

primitive-maybe (empty) → 0.1.0

raw patch · 8 files changed

+281/−0 lines, 8 filesdep +basedep +primitivedep +primitive-maybesetup-changed

Dependencies added: base, primitive, primitive-maybe

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Andrew Martin (c) 2018++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Andrew Martin nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,1 @@+# primitive-maybe
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ primitive-maybe.cabal view
@@ -0,0 +1,46 @@+cabal-version: 2.0+name: primitive-maybe+version: 0.1.0+synopsis: Arrays of Maybes+description:+  This library provides types for working with arrays of @Maybe@+  values. The types in this library can be used as replacements+  for @Array (Maybe a)@ and @SmallArray (Maybe a)@ that consume+  less memory and have fewer indirections.+homepage: https://github.com/andrewthad/primitive-maybe#readme+bug-reports: https://github.com/andrewthad/primitive-maybe/issues+author: Andrew Martin+maintainer: andrew.thaddeus@gmail.com+copyright: 2018 Andrew Martin+license: BSD3+license-file: LICENSE+build-type: Simple+category: Array+extra-source-files: README.md++source-repository head+  type: git+  location: https://github.com/andrewthad/primitive-maybe++library+  exposed-modules:+    Data.Primitive.Array.Maybe+    Data.Primitive.SmallArray.Maybe+  other-modules:+    Data.Primitive.Maybe.Internal+  hs-source-dirs: src+  build-depends:+      base >=4.9.1.0 && <5+    , primitive >= 0.6.4+  ghc-options: -O2 -Wall+  default-language: Haskell2010++test-suite test+  type: exitcode-stdio-1.0+  main-is: Main.hs+  hs-source-dirs: test+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      base >=4.9.1.0 && <5+    , primitive-maybe+  default-language: Haskell2010
+ src/Data/Primitive/Array/Maybe.hs view
@@ -0,0 +1,95 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE RoleAnnotations #-}++-- | This provides an interface to working with boxed arrays+-- with elements of type @Maybe a@. That is:+--+-- > MaybeArray a ≅ Array (Maybe a)+--+-- However, this type provided by this module is more efficient+-- than its naive @Array@ counterpart. It consumes less+-- memory and has fewer heap indirections.+module Data.Primitive.Array.Maybe+  ( MaybeArray+  , MutableMaybeArray+  , indexMaybeArray+  , newMaybeArray+  , readMaybeArray+  , writeMaybeArray+  , sequenceMaybeArray+  , unsafeFreezeMaybeArray+  ) where++import Control.Monad.Primitive+import Data.Primitive.Array++import Data.Primitive.Maybe.Internal (nothingSurrogate)+import GHC.Exts (Any,reallyUnsafePtrEquality#)+import Unsafe.Coerce (unsafeCoerce)++newtype MaybeArray a = MaybeArray (Array Any)+newtype MutableMaybeArray s a = MutableMaybeArray (MutableArray s Any)++type role MaybeArray representational+type role MutableMaybeArray nominal representational++unsafeToMaybe :: Any -> Maybe a+unsafeToMaybe a =+  case reallyUnsafePtrEquality# a nothingSurrogate of+    0# -> Just (unsafeCoerce a)+    _  -> Nothing+{-# INLINE unsafeToMaybe #-}++newMaybeArray :: PrimMonad m => Int -> Maybe a -> m (MutableMaybeArray (PrimState m) a)+{-# INLINE newMaybeArray #-}+newMaybeArray i ma = case ma of+  Just a -> do+    x <- newArray i (unsafeCoerce a)+    return (MutableMaybeArray x)+  Nothing -> do+    x <- newArray i nothingSurrogate+    return (MutableMaybeArray x)++indexMaybeArray :: MaybeArray a -> Int -> Maybe a+{-# INLINE indexMaybeArray #-}+indexMaybeArray (MaybeArray a) ix =+  let (# v #) = indexArray## a ix+   in unsafeToMaybe v++readMaybeArray :: PrimMonad m => MutableMaybeArray (PrimState m) a -> Int -> m (Maybe a)+{-# INLINE readMaybeArray #-}+readMaybeArray (MutableMaybeArray m) ix = do+  a <- readArray m ix+  return (unsafeToMaybe a)++writeMaybeArray :: PrimMonad m => MutableMaybeArray (PrimState m) a -> Int -> Maybe a -> m ()+{-# INLINE writeMaybeArray #-}+writeMaybeArray (MutableMaybeArray marr) ix ma = case ma of+  Just a -> writeArray marr ix (unsafeCoerce a)+  Nothing -> writeArray marr ix nothingSurrogate++-- | This is like calling @sequence@ on an 'Array'. However, in+-- the event that all the values are @Just@, it does not need+-- to allocate a new array since the array backing the @MaybeArray@+-- can be reused.+sequenceMaybeArray :: MaybeArray a -> Maybe (Array a)+sequenceMaybeArray m@(MaybeArray a) =+  if hasNothing m then Nothing else Just (unsafeCoerce a)++hasNothing :: MaybeArray a -> Bool+hasNothing (MaybeArray a) = go 0 where+  go !ix = if ix < sizeofArray a+    then+      let (# v #) = indexArray## a ix+       in case reallyUnsafePtrEquality# v nothingSurrogate of+            0# -> True+            _  -> go (ix + 1)+    else False++unsafeFreezeMaybeArray :: PrimMonad m => MutableMaybeArray (PrimState m) a -> m (MaybeArray a)+{-# INLINE unsafeFreezeMaybeArray #-}+unsafeFreezeMaybeArray (MutableMaybeArray ma) = do+  a <- unsafeFreezeArray ma+  return (MaybeArray a)
+ src/Data/Primitive/Maybe/Internal.hs view
@@ -0,0 +1,10 @@+module Data.Primitive.Maybe.Internal+  ( nothingSurrogate+  ) where++import GHC.Exts (Any)++nothingSurrogate :: Any+nothingSurrogate = error "nothingSurrogate: This value should not be forced!"+{-# NOINLINE nothingSurrogate #-}+
+ src/Data/Primitive/SmallArray/Maybe.hs view
@@ -0,0 +1,95 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE RoleAnnotations #-}++-- | This provides an interface to working with boxed arrays+-- with elements of type @Maybe a@. That is:+--+-- > SmallMaybeArray a ≅ SmallArray (Maybe a)+--+-- However, this type provided by this module is more efficient+-- than its naive @SmallArray@ counterpart. It consumes less+-- memory and has fewer heap indirections.+module Data.Primitive.SmallArray.Maybe+  ( SmallMaybeArray+  , SmallMutableMaybeArray+  , indexSmallMaybeArray+  , newSmallMaybeArray+  , readSmallMaybeArray+  , writeSmallMaybeArray+  , sequenceSmallMaybeArray+  , unsafeFreezeSmallMaybeArray+  ) where++import Control.Monad.Primitive+import Data.Primitive.SmallArray++import Data.Primitive.Maybe.Internal (nothingSurrogate)+import GHC.Exts (Any,reallyUnsafePtrEquality#)+import Unsafe.Coerce (unsafeCoerce)++newtype SmallMaybeArray a = SmallMaybeArray (SmallArray Any)+newtype SmallMutableMaybeArray s a = SmallMutableMaybeArray (SmallMutableArray s Any)++type role SmallMaybeArray representational+type role SmallMutableMaybeArray nominal representational++unsafeToMaybe :: Any -> Maybe a+unsafeToMaybe a =+  case reallyUnsafePtrEquality# a nothingSurrogate of+    0# -> Just (unsafeCoerce a)+    _  -> Nothing+{-# INLINE unsafeToMaybe #-}++newSmallMaybeArray :: PrimMonad m => Int -> Maybe a -> m (SmallMutableMaybeArray (PrimState m) a)+{-# INLINE newSmallMaybeArray #-}+newSmallMaybeArray i ma = case ma of+  Just a -> do+    x <- newSmallArray i (unsafeCoerce a)+    return (SmallMutableMaybeArray x)+  Nothing -> do+    x <- newSmallArray i nothingSurrogate+    return (SmallMutableMaybeArray x)++indexSmallMaybeArray :: SmallMaybeArray a -> Int -> Maybe a+{-# INLINE indexSmallMaybeArray #-}+indexSmallMaybeArray (SmallMaybeArray a) ix =+  let (# v #) = indexSmallArray## a ix+   in unsafeToMaybe v++readSmallMaybeArray :: PrimMonad m => SmallMutableMaybeArray (PrimState m) a -> Int -> m (Maybe a)+{-# INLINE readSmallMaybeArray #-}+readSmallMaybeArray (SmallMutableMaybeArray m) ix = do+  a <- readSmallArray m ix+  return (unsafeToMaybe a)++writeSmallMaybeArray :: PrimMonad m => SmallMutableMaybeArray (PrimState m) a -> Int -> Maybe a -> m ()+{-# INLINE writeSmallMaybeArray #-}+writeSmallMaybeArray (SmallMutableMaybeArray marr) ix ma = case ma of+  Just a -> writeSmallArray marr ix (unsafeCoerce a)+  Nothing -> writeSmallArray marr ix nothingSurrogate++-- | This is like calling @sequence@ on a 'SmallArray'. However, in+-- the event that all the values are @Just@, it does not need+-- to allocate a new array since the array backing the @SmallMaybeArray@+-- can be reused.+sequenceSmallMaybeArray :: SmallMaybeArray a -> Maybe (SmallArray a)+sequenceSmallMaybeArray m@(SmallMaybeArray a) =+  if hasNothing m then Nothing else Just (unsafeCoerce a)++hasNothing :: SmallMaybeArray a -> Bool+hasNothing (SmallMaybeArray a) = go 0 where+  go !ix = if ix < sizeofSmallArray a+    then+      let (# v #) = indexSmallArray## a ix+       in case reallyUnsafePtrEquality# v nothingSurrogate of+            0# -> True+            _  -> go (ix + 1)+    else False++unsafeFreezeSmallMaybeArray :: PrimMonad m => SmallMutableMaybeArray (PrimState m) a -> m (SmallMaybeArray a)+{-# INLINE unsafeFreezeSmallMaybeArray #-}+unsafeFreezeSmallMaybeArray (SmallMutableMaybeArray ma) = do+  a <- unsafeFreezeSmallArray ma+  return (SmallMaybeArray a)
+ test/Main.hs view
@@ -0,0 +1,2 @@+main :: IO ()+main = putStrLn "Test suite not yet implemented"