@@ -90,6 +90,9 @@ import Control.DeepSeq (NFData(..))
9090import Control.Monad (when)
9191import Control.Monad.IO.Class (MonadIO(..))
9292import Data.Functor.Identity (runIdentity)
93+#if __GLASGOW_HASKELL__ < 808
94+import Data.Semigroup (Semigroup(..))
95+#endif
9396import Data.Word (Word8)
9497import Foreign.C.String (CString)
9598import Foreign.C.Types (CSize(..), CInt(..))
@@ -100,7 +103,7 @@ import Foreign.Storable (Storable(..))
100103import Prelude hiding (length, foldr, read, unlines, splitAt)
101104import Text.Read (readPrec, readListPrec, readListPrecDefault)
102105
103−import GHC.Base (Addr#, realWorld#)
106+import GHC.Base (Addr#, nullAddr#, realWorld#)
104107import GHC.Exts (IsList, IsString(..))
105108import GHC.ForeignPtr (ForeignPtr(..), newForeignPtr_)
106109import GHC.IO (IO(IO), unsafePerformIO)
@@ -897,6 +900,40 @@ read = D.fromStreamD . toStreamD
897900-- Semigroup and Monoid
898901-------------------------------------------------------------------------------
899902
903+-- Splice two immutable arrays creating a new array.
904+{-# INLINE spliceTwo #-}
905+spliceTwo :: (MonadIO m, Storable a) => Array a -> Array a -> m (Array a)
906+spliceTwo arr1 arr2 = do
907+ let src1 = unsafeForeignPtrToPtr (aStart arr1)
908+ src2 = unsafeForeignPtrToPtr (aStart arr2)
909+ len1 = aEnd arr1 `minusPtr` src1
910+ len2 = aEnd arr2 `minusPtr` src2
911+
912+ arr <- liftIO $ newArray (len1 + len2)
913+ let dst = unsafeForeignPtrToPtr (aStart arr)
914+
915+ -- XXX Should we use copyMutableByteArray# instead? Is there an overhead to
916+ -- ccall?
917+ liftIO $ do
918+ memcpy (castPtr dst) (castPtr src1) len1
919+ touchForeignPtr (aStart arr1)
920+ memcpy (castPtr (dst `plusPtr` len1)) (castPtr src2) len2
921+ touchForeignPtr (aStart arr2)
922+ return arr { aEnd = dst `plusPtr` (len1 + len2) }
923+
924+instance Storable a => Semigroup (Array a) where
925+ arr1 <> arr2 = unsafeInlineIO $ spliceTwo arr1 arr2
926+
927+nullForeignPtr :: ForeignPtr a
928+nullForeignPtr = ForeignPtr nullAddr# (error "nullForeignPtr")
929+
930+nil :: Array a
931+nil = Array nullForeignPtr (Ptr nullAddr#) (Ptr nullAddr#)
932+
933+instance Storable a => Monoid (Array a) where
934+ mempty = nil
935+ mappend = (<>)
936+
900937-------------------------------------------------------------------------------
901938-- IO
902939-------------------------------------------------------------------------------
@@ -944,25 +981,6 @@ unlines sep (D.Stream step state) = D.Stream step' (OuterLoop state)
944981 return $ D.Yield x (InnerLoop st startf
945982 (p `plusPtr` (sizeOf (undefined :: a))) end)
946983
947−-- Splice two immutable arrays creating a new array.
948−{-# INLINE spliceTwo #-}
949−spliceTwo :: (MonadIO m, Storable a) => Array a -> Array a -> m (Array a)
950−spliceTwo arr1 arr2 = do
951− let src1 = unsafeForeignPtrToPtr (aStart arr1)
952− src2 = unsafeForeignPtrToPtr (aStart arr2)
953− len1 = aEnd arr1 `minusPtr` src1
954− len2 = aEnd arr2 `minusPtr` src2
955−
956− arr <- liftIO $ newArray (len1 + len2)
957− let dst = unsafeForeignPtrToPtr (aStart arr)
958−
959− liftIO $ do
960− memcpy (castPtr dst) (castPtr src1) len1
961− touchForeignPtr (aStart arr1)
962− memcpy (castPtr (dst `plusPtr` len1)) (castPtr src2) len2
963− touchForeignPtr (aStart arr2)
964− return arr { aEnd = dst `plusPtr` (len1 + len2) }
965−
966984-- Splice an array into a pre-reserved mutable array. The user must ensure
967985-- that there is enough space in the mutable array.
968986{-# INLINE spliceWith #-}