packages feed

ArrayRef (empty) → 0.1

raw patch · 42 files changed

+3840/−0 lines, 42 filesdep +basesetup-changed

Dependencies added: base

Files

+ ArrayRef.cabal view
@@ -0,0 +1,66 @@+Name:               ArrayRef+Version:            0.1+Category:           Data+Synopsis:           Unboxed references, dynamic arrays and more+Description:        This array library supports: unboxed references,+                    Monad-independent references, syntax sugar for mutable types,+                    a reimplemented Arrays library, changes in MArray usage,+                    and using dynamic (resizable) arrays+License:            BSD3+License-file:       LICENSE+Stability:          experimental+Author:             Bulat Ziganshin+Maintainer:         Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+Homepage:           http://haskell.org/haskellwiki/Library/ArrayRef++Build-type:         Simple+Tested-with:        GHC==6.8.2+Build-Depends:      base+Extensions:         CPP, FlexibleContexts, FlexibleInstances, FunctionalDependencies,+                    KindSignatures, ForeignFunctionInterface,+                    MagicHash, RankNTypes, ScopedTypeVariables, TypeOperators,+                    TypeSynonymInstances, UnboxedTuples, UnliftedFFITypes+ghc-options:         -O2 -Wall -optl-Wl,-s+ghc-prof-options:    -prof -auto-all++Exposed-modules:+                    Control.Concurrent.LockingBZ,+                    Control.Monad.STorIO,+                    Data.HasDefaultValue,+                    Data.Ref,+                    Data.SyntaxSugar,+                    Data.Unboxed,+                    Data.ArrayBZ.Boxed,+                    Data.ArrayBZ.Diff,+                    Data.ArrayBZ.Dynamic,+                    Data.ArrayBZ.IArray,+                    Data.ArrayBZ.IO,+                    Data.ArrayBZ.MArray,+                    Data.ArrayBZ.ST,+                    Data.ArrayBZ.Storable,+                    Data.ArrayBZ.Unboxed,+                    Data.ArrayBZ.Internals.Boxed,+                    Data.ArrayBZ.Internals.IArray,+                    Data.ArrayBZ.Internals.MArray,+                    Data.ArrayBZ.Internals.Unboxed,+                    Data.Ref.LazyST,+                    Data.Ref.Unboxed,+                    Data.Ref.Universal,+                    GHC.ArrBZ,+                    GHC.Unboxed+Extra-source-files:+                    README+                    TODO,+                    Hugs/Typeable.h,+                    Data/ArrayBZ/Internals/readme.txt,+                    Data/ArrayBZ/Internals/unused.hs,+                    Examples/SyntaxSugar.hs,+                    Examples/Universal.hs,+                    Examples/URef.hs,+                    Examples/Array/Boxed.hs,+                    Examples/Array/Diff.hs,+                    Examples/Array/Dynamic.hs,+                    Examples/Array/IO.hs,+                    Examples/Array/ST.hs,+                    Examples/Array/Storable.hs,+                    Examples/Array/Unboxed.hs
+ Control/Concurrent/LockingBZ.hs view
@@ -0,0 +1,183 @@+{-# LANGUAGE CPP, FunctionalDependencies, FlexibleInstances, MultiParamTypeClasses #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Control.Concurrent.LockingBZ
+-- Copyright   :  (c) Bulat Ziganshin <Bulat.Ziganshin@gmail.com> 2006
+-- License     :  BSD-style (see the file libraries/base/LICENSE)
+--
+-- Maintainer  :  libraries@haskell.org
+-- Stability   :  experimental
+-- Portability :  non-portable (concurrency)
+--
+-- Attaching lock to immutable value.
+--
+-----------------------------------------------------------------------------
+
+module Control.Concurrent.LockingBZ
+  (
+          -- * Locking
+
+          -- $intro
+
+          -- ** The 'WithLocking h' type constructor
+        WithLocking(..),        -- instance of Show
+
+          -- ** Attaching lock to value
+        addLocking,             -- :: h -> IO (WithLocking h)
+        withLocking,            -- :: h -> (WithLocking h -> IO a) -> IO a
+
+          -- ** Using value inside lock
+#if defined (__GLASGOW_HASKELL__) || defined (__HUGS__)
+        Locking(..),
+#else
+        lock,
+#endif
+
+          -- ** Promoting operations to use locks
+        liftLock1,
+        liftLock2,
+        liftLock3,
+        liftLock4,
+        liftLock5,
+
+   ) where
+
+import Control.Concurrent.MVar
+import Control.Exception as Exception
+
+{- $intro
+
+This library allows to attach lock to any immutable value so that access
+to this value can be obtained only via the 'lock' operation that ensures
+that this value will never be used at the same time by concurrent threads.
+Lock attached to value by 'addLocking' operation, it's also possible to run
+code block with locked version of some value by 'withLocking' operation.
+
+To work with value contained inside lock, you should use 'lock' operation;
+it's usage is very like to using 'withMVar' for the same purpose, but you
+don't got ability to return new value of internal data from the action
+performed. On the other side, 'lock' operation is about two times faster
+than 'withMVar' according to my tests. There are also 'liftLock*'
+operations that simplifies promoting operations on original value to
+operations on it's locked version. Hugs/GHC version of this library defines
+'lock' as operation of class 'Locking' that opens possibility to define
+alternative 'lock' implementations.
+
+First usage example - adding lock to mutable array and promoting the mutable
+array with lock to support mutable array interface again. This can be done
+with any objects what are accessed through some interface defined via type
+class:
+
+>   import Control.Concurrent.Locking
+>
+>   type WithLocking2 a e m = WithLocking (a e m)
+>
+>   instance (MArray a e m) => (MArray (WithLocking2 a) e m) where
+>       newArray lu e = newArray lu e >>= addLocking
+>       newArray_ lu  = newArray_ lu  >>= addLocking
+>       unsafeRead = liftLock2 unsafeRead
+>       unsafeWrite = liftLock3 unsafeWrite
+>
+>   main = do arr <- newArray (0,9) 0 >>= addLocking
+>             readArray arr 0 >>= writeArray arr 1
+>             .....
+>
+
+Another example where 'lock' operation used to get exclusive access to file
+while performing sequence of operations on it:
+
+>   main = do lh <- openBinaryFile "test" ReadMode >>= addLocking
+>             ....
+>             str <- readStringAt lh pos
+>             ....
+>
+>   readStringAt lh pos =
+>       lock lh $ \h -> do
+>           saved_pos <- hTell h
+>           hSeek h AbsoluteSeek pos
+>           str <- hGetLine h
+>           hSeek h AbsoluteSeek saved_pos
+>           return str
+
+In this example, any thread can use 'readStringAt' on the same locked handle
+without risk to interfere with each other's operation
+
+-}
+
+
+-- -----------------------------------------------------------------------------
+-- 'WithLocking' type constructor and it's constructor functions
+
+-- | Type constructor that attaches lock to immutable value @h@
+data WithLocking h = WithLocking h !(MVar ())
+
+instance (Show h) => Show (WithLocking h) where
+    show (WithLocking h _) = "WithLocking ("++ show h ++")"
+
+-- | Add lock to object to ensure it's proper use in concurrent threads
+addLocking :: h -> IO (WithLocking h)
+addLocking h = do
+    mvar <- newMVar ()
+    return (WithLocking h mvar)
+
+-- | Run @action@ with locked version of object
+withLocking :: h -> (WithLocking h -> IO a) -> IO a
+withLocking h action = do
+    addLocking h >>= action
+
+-- -----------------------------------------------------------------------------
+-- 'lock' operation definition: use MPTC+FD for Hugs/GHC or simple function for
+-- compilers that don't support MPTC+FD
+
+#if defined (__GLASGOW_HASKELL__) || defined (__HUGS__)
+
+-- | Define class of locking implementations, where 'lh' holds lock around 'h'
+class Locking lh h | lh->h where
+    -- | Perform action while exclusively locking wrapped object
+    -- (faster analog of using 'withMVar' for the same purpose)
+    lock :: lh -> (h->IO a) -> IO a
+
+instance Locking (WithLocking h) h where
+    {-# INLINE lock #-}
+    lock
+
+#else
+
+{-# INLINE lock #-}
+-- | Perform action while exclusively locking wrapped object
+-- (faster analog of using 'withMVar' for the same purpose)
+lock :: (WithLocking h) -> (h->IO a) -> IO a
+lock
+
+#endif
+     (WithLocking h mvar) action = do
+        Exception.catch (do takeMVar mvar
+                            result <- action h
+                            putMVar mvar ()
+                            return result
+                        )
+                        (\e -> do tryPutMVar mvar (); throw e)
+
+-- -----------------------------------------------------------------------------
+-- Helper operations - wrappers around 'lock'
+
+{-# INLINE liftLock1 #-}
+-- | Lift 1-parameter action to operation on locked variable
+liftLock1 action h         = lock h (\a -> action a)
+
+{-# INLINE liftLock2 #-}
+-- | Lift 2-parameter action to operation on locked variable
+liftLock2 action h x       = lock h (\a -> action a x)
+
+{-# INLINE liftLock3 #-}
+-- | Lift 3-parameter action to operation on locked variable
+liftLock3 action h x y     = lock h (\a -> action a x y)
+
+{-# INLINE liftLock4 #-}
+-- | Lift 4-parameter action to operation on locked variable
+liftLock4 action h x y z   = lock h (\a -> action a x y z)
+
+{-# INLINE liftLock5 #-}
+-- | Lift 5-parameter action to operation on locked variable
+liftLock5 action h x y z t = lock h (\a -> action a x y z t)
+
+ Control/Monad/STorIO.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE CPP #-}+{- |+   Module     : Control.Monad.STorIO+   Copyright  : Copyright (C) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: GHC/Hugs++Unification of ST and IO operations!++-}++module Control.Monad.STorIO (+           STorIO(..),+           IOSpecific,+           IOSpecific2,+           IOSpecific3,+       )+where++#ifdef __GLASGOW_HASKELL__++import GHC.Unboxed++#else++import Control.Monad.ST+import qualified Control.Monad.ST.Lazy as Lazy++-- ---------------------------------------------------------------------------+-- | That's all we need to unify ST and IO operations!++class (Monad m) => STorIO m s | m->s where+    mLift :: IO a -> m a++instance STorIO (ST s) s where+    {-# INLINE mLift #-}+    mLift = unsafeIOToST++instance STorIO (Lazy.ST s) s where+    {-# INLINE mLift #-}+    mLift = Lazy.unsafeIOToST++instance STorIO IO () where+    {-# INLINE mLift #-}+    mLift = id++-- | Type functions which converts universal ST/IO types to IO-specific ones+type IOSpecific  a = a ()+type IOSpecific2 a b = a () b+type IOSpecific3 a = a ()++#endif+
+ Data/ArrayBZ/Boxed.hs view
@@ -0,0 +1,26 @@+{- |+   Module     : Data.ArrayBZ.Boxed+   Copyright  : (c) The University of Glasgow 2001 & (c) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: Hugs/GHC++Boxed arrays++-}++module Data.ArrayBZ.Boxed (+           Array,+           IOArray,+           STArray,+           module Data.Ix,+           module Data.ArrayBZ.Internals.IArray,+           module Data.ArrayBZ.Internals.MArray,+  ) where++import Data.Ix+import Data.ArrayBZ.Internals.Boxed+import Data.ArrayBZ.Internals.IArray+import Data.ArrayBZ.Internals.MArray
+ Data/ArrayBZ/Diff.hs view
@@ -0,0 +1,305 @@+{-# LANGUAGE CPP, TypeSynonymInstances, FlexibleInstances, FlexibleContexts,+  MultiParamTypeClasses #-}+{- |+   Module     : Data.ArrayBZ.Diff+   Copyright  : (c) The University of Glasgow 2001 & (c) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: GHC/Hugs++Functional arrays with constant-time update.++-}++module Data.ArrayBZ.Diff (++    -- * Diff array types++    -- | Diff arrays have an immutable interface, but rely on internal+    -- updates in place to provide fast functional update operator+    -- '//'.+    --+    -- When the '//' operator is applied to a diff array, its contents+    -- are physically updated in place. The old array silently changes+    -- its representation without changing the visible behavior:+    -- it stores a link to the new current array along with the+    -- difference to be applied to get the old contents.+    --+    -- So if a diff array is used in a single-threaded style,+    -- i.e. after '//' application the old version is no longer used,+    -- @a'!'i@ takes O(1) time and @a '//' d@ takes O(@length d@).+    -- Accessing elements of older versions gradually becomes slower.+    --+    -- Updating an array which is not current makes a physical copy.+    -- The resulting array is unlinked from the old family. So you+    -- can obtain a version which is guaranteed to be current and+    -- thus have fast element access by @a '//' []@.++    -- Possible improvement for the future (not implemented now):+    -- make it possible to say "I will make an update now, but when+    -- I later return to the old version, I want it to mutate back+    -- instead of being copied".++    IOToDiffArray, -- data IOToDiffArray+                   --     (a :: * -> * -> *) -- internal mutable array+                   --     (i :: *)           -- indices+                   --     (e :: *)           -- elements++    -- | Type synonyms for the two most important IO array types.++    -- Two most important diff array types are fully polymorphic+    -- lazy boxed DiffArray:+    DiffArray,     -- = IOToDiffArray IOArray+    -- ...and strict unboxed DiffUArray, working only for elements+    -- of primitive types but more compact and usually faster:+    DiffUArray,    -- = IOToDiffArray IOUArray++    -- * Overloaded immutable array interface++    -- | Module "Data.ArrayBZ.Internals.IArray" provides the interface+    -- of diff arrays. They are instances of class 'IArray'.+    module Data.ArrayBZ.Internals.IArray,++    -- * Low-level interface++    -- | These are really internal functions, but you will need them+    -- to make further 'IArray' instances of various diff array types+    -- (for either more 'MArray' types or more unboxed element types).+    newDiffArray, readDiffArray, replaceDiffArray+    )+    where++------------------------------------------------------------------------+-- Imports.++import Data.Ix++import System.IO.Unsafe   ( unsafePerformIO )+import Control.Exception  ( evaluate )+import Control.Concurrent.MVar ( MVar, newMVar, takeMVar, putMVar, readMVar )++import Data.ArrayBZ.Internals.IArray+import Data.ArrayBZ.Internals.MArray+import Data.ArrayBZ.Boxed+import Data.ArrayBZ.Unboxed+import Data.HasDefaultValue+import Data.Unboxed++------------------------------------------------------------------------+-- Diff array types.++-- | An arbitrary 'MArray' type living in the 'IO' monad can be converted+-- to a diff array.++newtype IOToDiffArray a i e =+    DiffArray {varDiffArray :: MVar (DiffArrayData a i e)}++-- Internal representation: either a mutable array, or a link to+-- another diff array patched with a list of index+element pairs.+data DiffArrayData a i e = Current (a i e)+                         | Diff (IOToDiffArray a i e) [(Int, e)]++-- | Fully polymorphic lazy boxed diff array.+type DiffArray  = IOToDiffArray IOArray++-- | Strict unboxed diff array, working only for elements+-- of primitive types but more compact and usually faster than 'DiffArray'.+type DiffUArray = IOToDiffArray IOUArray++------------------------------------------------------------------------+-- Instances.++instance HasBounds a => HasBounds (IOToDiffArray a) where+    bounds a = unsafePerformIO $ boundsDiffArray a++instance IArray DiffArray e where+    unsafeArray   lu ies = unsafePerformIO $ newDiffArray lu ies+    unsafeAt      a i    = unsafePerformIO $ a `readDiffArray` i+    unsafeReplace a ies  = unsafePerformIO $ a `replaceDiffArray1` ies++instance (Unboxed e) => IArray DiffUArray e where+    unsafeArray   lu ies = unsafePerformIO $ newDiffArray lu ies+    unsafeAt      a i    = unsafePerformIO $ a `readDiffArray` i+    unsafeReplace a ies  = unsafePerformIO $ a `replaceDiffArray2` ies++------------------------------------------------------------------------+-- Showing DiffArrays.++instance (Ix i, Show i, Show e) => Show (DiffArray i e) where+  showsPrec = showsIArray++instance (Ix i, Show i, Show e, Unboxed e, HasDefaultValue e) => Show (DiffUArray i e) where+  showsPrec = showsIArray++-- ---------------------------------------------------------------------------+-- Comparing DiffArrays.++instance (Ix i, Eq i, Eq e) => Eq (DiffArray i e) where+    (==) = eqIArray++instance (Ix i, Ord i, Ord e) => Ord (DiffArray i e) where+    compare = cmpIArray++instance (Ix i, Eq i, Eq e, Unboxed e, HasDefaultValue e) => Eq (DiffUArray i e) where+    (==) = eqIArray++instance (Ix i, Ord i, Ord e, Unboxed e, HasDefaultValue e) => Ord (DiffUArray i e) where+    compare = cmpIArray++------------------------------------------------------------------------+-- Helper functions.++newDiffArray :: (MArray a e IO, Ix i)+             => (i,i)+             -> [(Int, e)]+             -> IO (IOToDiffArray a i e)+newDiffArray (l,u) ies = do+    a <- newArray_ (l,u)+    sequence_ [unsafeWrite a i e | (i, e) <- ies]+    var <- newMVar (Current a)+    return (DiffArray var)++readDiffArray :: (MArray a e IO, Ix i)+              => IOToDiffArray a i e+              -> Int+              -> IO e+a `readDiffArray` i = do+    d <- readMVar (varDiffArray a)+    case d of+        Current a'  -> unsafeRead a' i+        Diff a' ies -> maybe (readDiffArray a' i) return (lookup i ies)++replaceDiffArray :: (MArray a e IO, Ix i)+                => IOToDiffArray a i e+                -> [(Int, e)]+                -> IO (IOToDiffArray a i e)+a `replaceDiffArray` ies = do+    d <- takeMVar (varDiffArray a)+    case d of+        Current a' -> case ies of+            [] -> do+                -- We don't do the copy when there is nothing to change+                -- and this is the current version. But see below.+                putMVar (varDiffArray a) d+                return a+            _:_ -> do+                diff <- sequence [do e <- unsafeRead a' i; return (i, e)+                                  | (i, _) <- ies]+                sequence_ [unsafeWrite a' i e | (i, e) <- ies]+                var' <- newMVar (Current a')+                putMVar (varDiffArray a) (Diff (DiffArray var') diff)+                return (DiffArray var')+        Diff _ _ -> do+            -- We still do the copy when there is nothing to change+            -- but this is not the current version. So you can use+            -- 'a // []' to make sure that the resulting array has+            -- fast element access.+            putMVar (varDiffArray a) d+            a' <- thawDiffArray a+                -- thawDiffArray gives a fresh array which we can+                -- safely mutate.+            sequence_ [unsafeWrite a' i e | (i, e) <- ies]+            var' <- newMVar (Current a')+            return (DiffArray var')++-- The elements of the diff list might recursively reference the+-- array, so we must seq them before taking the MVar to avoid+-- deadlock.+replaceDiffArray1 :: (MArray a e IO, Ix i)+                => IOToDiffArray a i e+                -> [(Int, e)]+                -> IO (IOToDiffArray a i e)+a `replaceDiffArray1` ies = do+    mapM_ (evaluate . fst) ies+    a `replaceDiffArray` ies++-- If the array contains unboxed elements, then the elements of the+-- diff list may also recursively reference the array from inside+-- replaceDiffArray, so we must seq them too.+replaceDiffArray2 :: (MArray a e IO, Ix i)+                => IOToDiffArray a i e+                -> [(Int, e)]+                -> IO (IOToDiffArray a i e)+a `replaceDiffArray2` ies = do+    mapM_ (\(a,b) -> do evaluate a; evaluate b) ies+    a `replaceDiffArray` ies++boundsDiffArray :: (HasBounds a, Ix ix)+                => IOToDiffArray a ix e+                -> IO (ix,ix)+boundsDiffArray a = do+    d <- readMVar (varDiffArray a)+    case d of+        Current a' -> return (bounds a')+        Diff a' _  -> boundsDiffArray a'++freezeDiffArray :: (MArray a e IO, Ix ix)+                => a ix e+                -> IO (IOToDiffArray a ix e)+freezeDiffArray a = do+    lu <- getBounds a+    a' <- newArray_ lu+    sequence_ [unsafeRead a i >>= unsafeWrite a' i | i <- [0 .. rangeSize lu - 1]]+    var <- newMVar (Current a')+    return (DiffArray var)++{-# RULES+"freeze/DiffArray" freeze = freezeDiffArray+    #-}++-- unsafeFreezeDiffArray is really unsafe. Better don't use the old+-- array at all after freezing. The contents of the source array will+-- be changed when '//' is applied to the resulting array.++unsafeFreezeDiffArray :: (MArray a e IO, Ix ix)+                      => a ix e+                      -> IO (IOToDiffArray a ix e)+unsafeFreezeDiffArray a = do+    var <- newMVar (Current a)+    return (DiffArray var)++{-# RULES+"unsafeFreeze/DiffArray" unsafeFreeze = unsafeFreezeDiffArray+    #-}++thawDiffArray :: (MArray a e IO, Ix ix)+              => IOToDiffArray a ix e+              -> IO (a ix e)+thawDiffArray a = do+    d <- readMVar (varDiffArray a)+    case d of+        Current a' -> do+            lu <- getBounds a'+            a'' <- newArray_ lu+            sequence_ [unsafeRead a' i >>= unsafeWrite a'' i | i <- [0 .. rangeSize lu - 1]]+            return a''+        Diff a' ies -> do+            a'' <- thawDiffArray a'+            sequence_ [unsafeWrite a'' i e | (i, e) <- ies]+            return a''++{-# RULES+"thaw/DiffArray" thaw = thawDiffArray+    #-}++-- unsafeThawDiffArray is really unsafe. Better don't use the old+-- array at all after thawing. The contents of the resulting array+-- will be changed when '//' is applied to the source array.++unsafeThawDiffArray :: (MArray a e IO, Ix ix)+                    => IOToDiffArray a ix e+                    -> IO (a ix e)+unsafeThawDiffArray a = do+    d <- readMVar (varDiffArray a)+    case d of+        Current a'  -> return a'+        Diff a' ies -> do+            a'' <- unsafeThawDiffArray a'+            sequence_ [unsafeWrite a'' i e | (i, e) <- ies]+            return a''++{-# RULES+"unsafeThaw/DiffArray" unsafeThaw = unsafeThawDiffArray+    #-}
+ Data/ArrayBZ/Dynamic.hs view
@@ -0,0 +1,180 @@+{-# LANGUAGE CPP, UndecidableInstances, FlexibleInstances, MultiParamTypeClasses #-}+{- |+   Module     : Data.ArrayBZ.Dynamic+   Copyright  : (c) The University of Glasgow 2001 & (c) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: Hugs/GHC++Arrays with dynamically changed bounds in IO and ST monads.++-}++module Data.ArrayBZ.Dynamic (+   -- $info+   -- * Type constructors+   Dynamic,+   DynamicIO,+   DynamicIOArray,+   DynamicIOUArray,+   DynamicST,+   DynamicSTArray,+   DynamicSTUArray,+   GrowBoundsF,+   -- * Operations+   newDynamicArray,+   newDynamicArray_,+   resizeDynamicArray,+   -- * Array growing strategies+   noGrow,+   growMinimally,+   growTwoTimes,+   -- Reexported MArray interface+   module Data.ArrayBZ.Internals.MArray+ ) where++import Data.Ref+import Data.ArrayBZ.Internals.MArray+import Data.ArrayBZ.IO+import Data.ArrayBZ.ST+#ifdef __GLASGOW_HASKELL__+import GHC.Arr                  ( unsafeIndex )+#endif+#ifdef __HUGS__+import Hugs.Array               ( unsafeIndex )+#endif++{- $info++Array with dynamically changed bounds can be created from any mutable array+type by using type converter Dynamic. I have created synonyms for widely used+array constructors, for example "DynamicIOUArray Int Double".+Dynamic array supports the same MArray and HasMutableBounds interfaces as other+mutable arrays, but they don't support HasBounds interface. Dynamic array can be+resized explicitly by operation `resizeDynamicArray`.++Dynamic array can also grow automatically when `writeArray` is used with index+that is out of current array bounds. For this to work, array should be created+using non-standard operations `newDynamicArray` or `newDynamicArray_`. The first+argument of these operations is "growing strategy", i.e. the function of type+`GrowBoundsF i`, other arguments are the same as for newArray/newArray_. The+predefined growing strategies include `noGrow` that disables automatic growing,+`growMinimally` that extends array only to include new index and `growTwoTimes`+that extend array at least 2 times each time it needs to grow.++When array grows, either explicitly or automatically, new elements are+initialized with `init` value if this array was created by+newArray/newDynamicArray.++-}++-- ---------------------------------------------------------------------------+-- Types++-- | Representation of dynamic array. Includes+--     * function to calculate new array bounds when it needs to grow+--     * optional value used for initializing new elements when array grows+--     * reference to current array contents+data Dynamic r a i e = Dynamic (GrowBoundsF i) (Maybe e) (r (a i e))++-- | Dynamic arrays in IO monad+type DynamicIO         = Dynamic IORef+-- |Dynamic version of IOArray+type DynamicIOArray    = DynamicIO IOArray+-- |Dynamic version of IOUArray+type DynamicIOUArray   = DynamicIO IOUArray++-- | Dynamic arrays in ST monad+type DynamicST       s =  Dynamic (STRef s)+-- |Dynamic version of STArray+type DynamicSTArray  s = (DynamicST s) (STArray  s)+-- |Dynamic version of STUArray+type DynamicSTUArray s = (DynamicST s) (STUArray s)++-- | This type represents function that calculates new array bounds when it needs to grow+type GrowBoundsF i  =  (i,i) -> i -> (i,i)++-- ---------------------------------------------------------------------------+-- Operations++-- | Create new dynamic array with default value for new cells set to `init`.+--   `f` is a growing strategy and may be `noGrow`, `growMinimally`+--    or `growTwoTimes`+newDynamicArray f bounds init = do+    arr <- newArray  bounds init+    a   <- newRef arr+    return (Dynamic f (Just init) a)++-- | Create new dynamic array where all new cells will remain uninitialized.+--   `f` is a growing strategy and may be `noGrow`, `growMinimally`+--    or `growTwoTimes`+newDynamicArray_ f bounds = do+    arr <- newArray_  bounds+    a   <- newRef arr+    return (Dynamic f Nothing a)++-- | Extend/shrink dynamic array to new bounds+resizeDynamicArray (Dynamic _ e a) newbounds = do+    arr <- readRef a+    bounds <- getBounds arr+    newarr <- case e of+                Just init -> newArray  newbounds init+                Nothing   -> newArray_ newbounds+    sequence_ [ readArray arr i >>= writeArray newarr i+              | i <- range bounds, inRange newbounds i ]+    writeRef a newarr++-- ---------------------------------------------------------------------------+-- Instances++instance (HasMutableBounds a m, Ref m r) => HasMutableBounds (Dynamic r a) m where+    {-# INLINE getBounds #-}+    getBounds (Dynamic _ _ a)  =  readRef a >>= getBounds++instance (MArray a e m, Ref m r) => MArray (Dynamic r a) e m where+    newArray_ =  newDynamicArray_ noGrow+    newArray  =  newDynamicArray  noGrow++    {-# INLINE unsafeRead #-}+    unsafeRead  (Dynamic _ _ a) i = do arr <- readRef a+                                       unsafeRead arr i++    {-# INLINE unsafeWrite #-}+    unsafeWrite (Dynamic _ _ a) i e = do arr <- readRef a+                                         unsafeWrite arr i e++    {-# INLINE writeArray #-}+    writeArray dyn@(Dynamic _ _ a) i e = do+        arr <- readRef a+        bounds <- getBounds arr+        if inRange bounds i+          then unsafeWrite arr (unsafeIndex bounds i) e+          else extendAndWrite dyn arr bounds i e++-- Helper function used to make `writeArray` look as non-recursive function,+-- what is required for GHC's optimization+extendAndWrite dyn@(Dynamic extend _ a) arr bounds i e = do+    resizeDynamicArray dyn (extend bounds i)+    writeArray dyn i e+++-- ---------------------------------------------------------------------------+-- Bounds growing functions, that can be used with newDynamicArray/newDynamicArray_++-- | No automatic growing at all. This "growing" method is compatible with any+-- bounds type+noGrow _ _ = error "Dynamic array: index out of bounds"++-- | Grow minimally - only to include new index in array bounds. This growing+-- method is compatible with any bounds type+growMinimally (l,u) i | inRange (l,i) u = (l,i)+                      | inRange (i,u) l = (i,u)+                      | otherwise = error "can't compute new bounds for dynamic array"++-- | Grow number of elements at least 2 times. This growing method is compatible+-- only with bounds belonging to class Num+growTwoTimes (l,u) i = if i<l then (min (l-(u-l)) i, u)+                              else (l, max (u+(u-l)) i)+
+ Data/ArrayBZ/IArray.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE CPP #-}+{- |+   Module     : Data.ArrayBZ.IArray+   Copyright  : (c) The University of Glasgow 2001 & (c) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: Hugs/GHC++Immutable arrays, with an overloaded interface.  For array types which+can be used with this interface, see the 'Array' type exported by this+module, and the "Data.ArrayBZ.Unboxed" and "Data.ArrayBZ.Diff" modules.++-}++module Data.ArrayBZ.IArray (+    -- * Array classes+    HasBounds,  -- :: (* -> * -> *) -> class+    IArray,     -- :: (* -> * -> *) -> * -> class++    module Data.Ix,++    -- * Immutable non-strict (boxed) arrays+    Array,++    -- * Array construction+    array,      -- :: (IArray a e, Ix i) => (i,i) -> [(i, e)] -> a i e+    listArray,  -- :: (IArray a e, Ix i) => (i,i) -> [e] -> a i e+    accumArray, -- :: (IArray a e, Ix i) => (e -> e' -> e) -> e -> (i,i) -> [(i, e')] -> a i e++    -- * Accessing arrays+    (!),        -- :: (IArray a e, Ix i) => a i e -> i -> e+    bounds,     -- :: (HasBounds a, Ix i) => a i e -> (i,i)+    indices,    -- :: (HasBounds a, Ix i) => a i e -> [i]+    elems,      -- :: (IArray a e, Ix i) => a i e -> [e]+    assocs,     -- :: (IArray a e, Ix i) => a i e -> [(i, e)]++    -- * Incremental array updates+    (//),       -- :: (IArray a e, Ix i) => a i e -> [(i, e)] -> a i e+    accum,      -- :: (IArray a e, Ix i) => (e -> e' -> e) -> a i e -> [(i, e')] -> a i e++    -- * Derived arrays+    amap,       -- :: (IArray a e', IArray a e, Ix i) => (e' -> e) -> a i e' -> a i e+    ixmap,      -- :: (IArray a e, Ix i, Ix j) => (i,i) -> (i -> j) -> a j e -> a i e+ )  where++import Data.Ix+import Data.ArrayBZ.Internals.IArray+import Data.ArrayBZ.Internals.Boxed (Array)
+ Data/ArrayBZ/IO.hs view
@@ -0,0 +1,193 @@+{-# LANGUAGE CPP, UnliftedFFITypes #-}+{-# INCLUDE "HsBase.hs" #-}+{- |+   Module     : Data.ArrayBZ.IO+   Copyright  : (c) The University of Glasgow 2001 & (c) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: Hugs/GHC++Mutable boxed and unboxed arrays in the IO monad.+-}++module Data.ArrayBZ.IO (+   -- * @IO@ arrays with boxed elements+   IOArray,             -- instance of: Eq, Typeable++   -- * @IO@ arrays with unboxed elements+   IOUArray,            -- instance of: Eq, Typeable+   castIOUArray,        -- :: IOUArray i a -> IO (IOUArray i b)++   -- * Overloaded mutable array interface+   module Data.ArrayBZ.MArray,++   -- * Doing I\/O with @IOUArray@s+   hGetArray,           -- :: Handle -> IOUArray Int Word8 -> Int -> IO Int+   hPutArray,           -- :: Handle -> IOUArray Int Word8 -> Int -> IO ()+ ) where++import Data.Word++import Data.ArrayBZ.MArray+import Data.ArrayBZ.Internals.Boxed   ( IOArray )+import Data.ArrayBZ.Internals.Unboxed++#ifdef __GLASGOW_HASKELL__+import Foreign+import Foreign.C++import GHC.IOBase hiding (IOArray)+import GHC.Handle+import GHC.Unboxed++-- ---------------------------------------------------------------------------+-- hGetArray++-- | Reads a number of 'Word8's from the specified 'Handle' directly+-- into an array.+hGetArray+        :: Handle               -- ^ Handle to read from+        -> IOUArray Int Word8   -- ^ Array in which to place the values+        -> Int                  -- ^ Number of 'Word8's to read+        -> IO Int+                -- ^ Returns: the number of 'Word8's actually+                -- read, which might be smaller than the number requested+                -- if the end of file was reached.++hGetArray handle (UMA l u (MUVec ptr)) count+  | count == 0+  = return 0+  | count < 0 || count > rangeSize (l,u)+  = illegalBufferSize handle "hGetArray" count+  | otherwise = do+      wantReadableHandle "hGetArray" handle $+        \ handle_@Handle__{ haFD=fd, haBuffer=ref, haIsStream=is_stream } -> do+        buf@Buffer{ bufBuf=raw, bufWPtr=w, bufRPtr=r } <- readIORef ref+        if bufferEmpty buf+           then readChunk fd is_stream ptr 0 count+           else do+                let avail = w - r+                copied <- if (count >= avail)+                            then do+                                memcpy_ba_baoff ptr raw r (fromIntegral avail)+                                writeIORef ref buf{ bufWPtr=0, bufRPtr=0 }+                                return avail+                            else do+                                memcpy_ba_baoff ptr raw r (fromIntegral count)+                                writeIORef ref buf{ bufRPtr = r + count }+                                return count++                let remaining = count - copied+                if remaining > 0+                   then do rest <- readChunk fd is_stream ptr copied remaining+                           return (rest + copied)+                   else return count++readChunk :: FD -> Bool -> RawBuffer -> Int -> Int -> IO Int+readChunk fd is_stream ptr init_off bytes = loop init_off bytes+ where+  loop :: Int -> Int -> IO Int+  loop off bytes | bytes <= 0 = return (off - init_off)+  loop off bytes = do+    r' <- readRawBuffer "readChunk" (fromIntegral fd) is_stream ptr+                                    (fromIntegral off) (fromIntegral bytes)+    let r = fromIntegral r'+    if r == 0+        then return (off - init_off)+        else loop (off + r) (bytes - r)++-- ---------------------------------------------------------------------------+-- hPutArray++-- | Writes an array of 'Word8' to the specified 'Handle'.+hPutArray+        :: Handle                       -- ^ Handle to write to+        -> IOUArray Int Word8           -- ^ Array to write from+        -> Int                          -- ^ Number of 'Word8's to write+        -> IO ()++hPutArray handle (UMA l u (MUVec raw)) count+  | count == 0+  = return ()+  | count < 0 || count > rangeSize (l,u)+  = illegalBufferSize handle "hPutArray" count+  | otherwise+   = do wantWritableHandle "hPutArray" handle $+          \ handle_@Handle__{ haFD=fd, haBuffer=ref, haIsStream=stream } -> do++          old_buf@Buffer{ bufBuf=old_raw, bufRPtr=r, bufWPtr=w, bufSize=size }+            <- readIORef ref++          -- enough room in handle buffer?+          if (size - w > count)+                -- There's enough room in the buffer:+                -- just copy the data in and update bufWPtr.+            then do memcpy_baoff_ba old_raw w raw (fromIntegral count)+                    writeIORef ref old_buf{ bufWPtr = w + count }+                    return ()++                -- else, we have to flush+            else do flushed_buf <- flushWriteBuffer fd stream old_buf+                    writeIORef ref flushed_buf+                    let this_buf =+                            Buffer{ bufBuf=raw, bufState=WriteBuffer,+                                    bufRPtr=0, bufWPtr=count, bufSize=count }+                    flushWriteBuffer fd stream this_buf+                    return ()++-- ---------------------------------------------------------------------------+-- Internal Utils++foreign import ccall unsafe "__hscore_memcpy_dst_off"+   memcpy_baoff_ba :: RawBuffer -> Int -> RawBuffer -> CSize -> IO (Ptr ())+foreign import ccall unsafe "__hscore_memcpy_src_off"+   memcpy_ba_baoff :: RawBuffer -> RawBuffer -> Int -> CSize -> IO (Ptr ())++illegalBufferSize :: Handle -> String -> Int -> IO a+illegalBufferSize handle fn sz =+        ioException (IOError (Just handle)+                            InvalidArgument  fn+                            ("illegal buffer size " ++ showsPrec 9 (sz::Int) [])+                            Nothing)++#else /* !__GLASGOW_HASKELL__ */+import Data.Char+import System.IO+import System.IO.Error+import Data.ArrayBZ.Internals.MArray++hGetArray :: Handle -> IOUArray Int Word8 -> Int -> IO Int+hGetArray handle arr count+  | count < 0 || count > rangeSize (bounds arr)+  = illegalBufferSize handle "hGetArray" count+  | otherwise = get 0+ where+  get i | i == count = return i+        | otherwise = do+                error_or_c <- try (hGetChar handle)+                case error_or_c of+                    Left ex+                        | isEOFError ex -> return i+                        | otherwise -> ioError ex+                    Right c -> do+                        unsafeWrite arr i (fromIntegral (ord c))+                        get (i+1)++hPutArray :: Handle -> IOUArray Int Word8 -> Int -> IO ()+hPutArray handle arr count+  | count < 0 || count > rangeSize (bounds arr)+  = illegalBufferSize handle "hPutArray" count+  | otherwise = put 0+ where+  put i | i == count = return ()+        | otherwise = do+                w <- unsafeRead arr i+                hPutChar handle (chr (fromIntegral w))+                put (i+1)++illegalBufferSize :: Handle -> String -> Int -> IO a+illegalBufferSize _ fn sz = ioError $+        userError (fn ++ ": illegal buffer size " ++ showsPrec 9 (sz::Int) [])+#endif /* !__GLASGOW_HASKELL__ */
+ Data/ArrayBZ/Internals/Boxed.hs view
@@ -0,0 +1,274 @@+{-# LANGUAGE CPP, TypeSynonymInstances, FlexibleInstances, MultiParamTypeClasses #-}+{- |+   Module     : Data.ArrayBZ.Internals.Boxed+   Copyright  : (c) The University of Glasgow 2001 & (c) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: GHC/Hugs++Boxed arrays++-}++module Data.ArrayBZ.Internals.Boxed+#ifdef __HUGS__+         ( -- * Types+           Array,+           IOArray,+           STArray,++           -- * Freeze/thaw operations+           freezeIOArray,+           thawIOArray,+           unsafeFreezeIOArray,+           freezeSTArray,+           thawSTArray,+           unsafeFreezeSTArray,+         )+#endif+   where++import Control.Monad.ST         ( ST, runST )+import Control.Monad.ST.Lazy    ( strictToLazyST )+import qualified Control.Monad.ST.Lazy as Lazy (ST)+import Data.Ix+import Data.Typeable+#include "Typeable.h"++import Data.ArrayBZ.Internals.IArray+import Data.ArrayBZ.Internals.MArray++#ifdef __HUGS__+-- ---------------------------------------------------------------------------+-- Hugs primitives are higher-level than GHC/NHC's+-- ---------------------------------------------------------------------------++import Hugs.Array as Arr+import Hugs.IOArray+import Hugs.ST++-----------------------------------------------------------------------------+-- Normal polymorphic arrays++instance HasBounds Array where+    bounds           = Arr.bounds++instance IArray Array e where+    unsafeArray      = Arr.unsafeArray+    unsafeAt         = Arr.unsafeAt+    unsafeReplace    = Arr.unsafeReplace+    unsafeAccum      = Arr.unsafeAccum+    unsafeAccumArray = Arr.unsafeAccumArray++-----------------------------------------------------------------------------+-- | Instance declarations for 'IOArray's++instance HasBounds IOArray where+    bounds      = boundsIOArray++instance HasMutableBounds IOArray IO where+    getBounds   = return . boundsIOArray++instance MArray IOArray e IO where+    newArray    = newIOArray+    unsafeRead  = unsafeReadIOArray+    unsafeWrite = unsafeWriteIOArray++-----------------------------------------------------------------------------+-- Polymorphic non-strict mutable arrays (ST monad)++instance HasBounds (STArray s) where+    bounds      = boundsSTArray++instance HasMutableBounds (STArray s) (ST s) where+    getBounds   = return . boundsSTArray++instance MArray (STArray s) e (ST s) where+    newArray    = newSTArray+    unsafeRead  = unsafeReadSTArray+    unsafeWrite = unsafeWriteSTArray++#else+-- ---------------------------------------------------------------------------+-- Non-Hugs implementation+-- ---------------------------------------------------------------------------++import Control.Monad.STorIO+import GHC.ArrBZ++-- ---------------------------------------------------------------------------+-- | Boxed mutable arrays++data BoxedMutableArray s i e  =  BMA !i !i !(MVec s e)++instance HasBounds (BoxedMutableArray s) where+    {-# INLINE bounds #-}+    bounds (BMA l u _) = (l,u)++instance (STorIO m s) => HasMutableBounds (BoxedMutableArray s) m where+    {-# INLINE getBounds #-}+    getBounds (BMA l u _) = return (l,u)++instance (STorIO m s) => MArray (BoxedMutableArray s) e m where+    newArray (l,u) init = do arr <- allocBoxed (rangeSize (l,u)) init+                             return (BMA l u arr)+    {-# INLINE unsafeRead #-}+    unsafeRead  (BMA _ _ arr) index  =  readBoxed  arr index+    {-# INLINE unsafeWrite #-}+    unsafeWrite (BMA _ _ arr) index  =  writeBoxed arr index++-- ---------------------------------------------------------------------------+-- | Boxed mutable arrays in ST monad++type STArray = BoxedMutableArray++-- ---------------------------------------------------------------------------+-- STArray also works in Lazy ST monad++instance MArray (STArray s) e (Lazy.ST s) where+    {-# INLINE newArray #-}+    newArray (l,u) init = strictToLazyST (newArray (l,u) init)+    {-# INLINE unsafeRead #-}+    unsafeRead  arr i   = strictToLazyST (unsafeRead  arr i)+    {-# INLINE unsafeWrite #-}+    unsafeWrite arr i e = strictToLazyST (unsafeWrite arr i e)++-- ---------------------------------------------------------------------------+-- | Boxed mutable arrays in IO monad++type IOArray = IOSpecific3 BoxedMutableArray++-- ---------------------------------------------------------------------------+-- | Boxed immutable arrays++data Array i e  =  BA !i !i !(Vec e)++instance HasBounds Array where+    {-# INLINE bounds #-}+    bounds (BA l u _) = (l,u)++instance IArray Array e where+    {-# INLINE unsafeArray #-}+    -- Create new array filled with (i,e) values+    unsafeArray lu ies = runST (withNewArray lu arrEleBottom (doReplace ies))+    {-# INLINE unsafeAt #-}+    unsafeAt (BA _ _ arr) index = indexBoxed arr index+    {-# INLINE unsafeReplace #-}+    -- Make a copy of array and perform (i,e) replacements+    unsafeReplace arr ies = runST (withArrayCopy arr (doReplace ies))+    {-# INLINE unsafeAccum #-}+    -- Make a copy of array and perform (i,e) accumulation in new array+    unsafeAccum f arr ies = runST (withArrayCopy arr (doAccum f ies))+    {-# INLINE unsafeAccumArray #-}+    -- Create new array accumulating (i,e) values+    unsafeAccumArray f init lu ies = runST (withNewArray lu init (doAccum f ies))+++-- Implementation helper functions -------------++-- Create new array and perform given action on it before freezing+withNewArray lu init action = do+    marr <- newArray lu init+    action marr+    unsafeFreezeBA marr++-- Make a copy of array and perform given action on it before freezing+withArrayCopy arr action = do+    marr <- thawBA arr+    action marr+    unsafeFreezeBA marr++-- Perform (i,e) replaces in mutable array+doReplace ies marr = do+    sequence_ [unsafeWrite marr i e | (i, e) <- ies]++-- Accumulate (i,e) values in mutable array+doAccum f ies marr = do+    sequence_ [do old <- unsafeRead marr i+                  unsafeWrite marr i (f old new)+              | (i, new) <- ies]++-- Mutable->immutable array conversion which takes a copy of contents+freezeBA ua@(BMA l u marr) = do+    arr <- freezeBoxed marr (sizeOfBA ua) arrEleBottom+    return (BA l u arr)++-- Immutable->mutable array conversion which takes a copy of contents+thawBA ua@(BA l u arr) = do+    marr <- thawBoxed arr (sizeOfBA ua) arrEleBottom+    return (BMA l u marr)++-- On-the-place mutable->immutable array conversion+unsafeFreezeBA (BMA l u marr) = do+    arr <- unsafeFreezeBoxed marr+    return (BA l u arr)++-- On-the-place immutable->mutable array conversion+unsafeThawBA ua@(BA l u arr) = do+    marr <- unsafeThawBoxed arr+    return (BMA l u marr)++-- | Number of array elements+sizeOfBA arr = rangeSize (bounds arr)++-- ---------------------------------------------------------------------------+-- | Freeze/thaw rules for IOArray++freezeIOArray       :: (Ix i) => IOArray i e -> IO (Array i e)+thawIOArray         :: (Ix i) => Array i e -> IO (IOArray i e)+unsafeFreezeIOArray :: (Ix i) => IOArray i e -> IO (Array i e)+unsafeThawIOArray   :: (Ix i) => Array i e -> IO (IOArray i e)++freezeIOArray       = freezeBA+thawIOArray         = thawBA+unsafeFreezeIOArray = unsafeFreezeBA+unsafeThawIOArray   = unsafeThawBA++{-# RULES+"freeze/IOArray" freeze = freezeIOArray+"thaw/IOArray"   thaw   = thawIOArray+"unsafeFreeze/IOArray" unsafeFreeze = unsafeFreezeIOArray+"unsafeThaw/IOArray"   unsafeThaw   = unsafeThawIOArray+    #-}++-- ---------------------------------------------------------------------------+-- | Freeze/thaw rules for STArray++freezeSTArray       :: (Ix i) => STArray s i e -> ST s (Array i e)+thawSTArray         :: (Ix i) => Array i e -> ST s (STArray s i e)+unsafeFreezeSTArray :: (Ix i) => STArray s i e -> ST s (Array i e)+unsafeThawSTArray   :: (Ix i) => Array i e -> ST s (STArray s i e)++freezeSTArray       = freezeBA+thawSTArray         = thawBA+unsafeFreezeSTArray = unsafeFreezeBA+unsafeThawSTArray   = unsafeThawBA++{-# RULES+"freeze/STArray" freeze = freezeSTArray+"thaw/STArray"   thaw   = thawSTArray+"unsafeFreeze/STArray" unsafeFreeze = unsafeFreezeSTArray+"unsafeThaw/STArray"   unsafeThaw   = unsafeThawSTArray+    #-}++-- ---------------------------------------------------------------------------+-- | Instances++instance (Ix i, Show i, Show e) => Show (Array i e) where+    showsPrec = showsIArray++instance (Ix i, Eq i, Eq e) => Eq (Array i e) where+    (==) = eqIArray++instance (Ix i, Ord i, Ord e) => Ord (Array i e) where+    compare = cmpIArray++#endif+++INSTANCE_TYPEABLE2(IOArray,iOArrayTc,"IOArray")++INSTANCE_TYPEABLE3(STArray,stArrayTc,"STArray")+
+ Data/ArrayBZ/Internals/IArray.hs view
@@ -0,0 +1,253 @@+{-# LANGUAGE CPP, MultiParamTypeClasses #-}+{- |+   Module     : Data.ArrayBZ.Internals.IArray+   Copyright  : (c) The University of Glasgow 2001 & (c) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: GHC/Hugs++Immutable arrays: class, general algorithms and Show/Ord/Eq implementations++-}++module Data.ArrayBZ.Internals.IArray where++import Control.Monad.ST         ( ST, runST )+import Data.Ix+#ifdef __GLASGOW_HASKELL__+import GHC.Arr                  ( unsafeIndex )+#endif+#ifdef __HUGS__+import Hugs.Array               ( unsafeIndex )+#endif++-----------------------------------------------------------------------------+-- Class of immutable arrays++-- | Class of array types with immutable bounds+-- (even if the array elements are mutable).+class HasBounds a where+    -- | Extracts the bounds of an array+    bounds :: Ix i => a i e -> (i,i)++{- | Class of immutable array types.++An array type has the form @(a i e)@ where @a@ is the array type+constructor (kind @* -> * -> *@), @i@ is the index type (a member of+the class 'Ix'), and @e@ is the element type.  The @IArray@ class is+parameterised over both @a@ and @e@, so that instances specialised to+certain element types can be defined.+-}+class HasBounds a => IArray a e where+    unsafeArray      :: Ix i => (i,i) -> [(Int, e)] -> a i e+    unsafeAt         :: Ix i => a i e -> Int -> e+    unsafeReplace    :: Ix i => a i e -> [(Int, e)] -> a i e+    unsafeAccum      :: Ix i => (e -> e' -> e) -> a i e -> [(Int, e')] -> a i e+    unsafeAccumArray :: Ix i => (e -> e' -> e) -> e -> (i,i) -> [(Int, e')] -> a i e++-----------------------------------------------------------------------------+-- Algorithms on immutable arrays++{-# INLINE array #-}+{-|+Constructs an immutable array from a pair of bounds and a list of+initial associations.++The bounds are specified as a pair of the lowest and highest bounds in+the array respectively.  For example, a one-origin vector of length 10+has bounds (1,10), and a one-origin 10 by 10 matrix has bounds+((1,1),(10,10)).++An association is a pair of the form @(i,x)@, which defines the value of+the array at index @i@ to be @x@.  The array is undefined if any index+in the list is out of bounds.  If any two associations in the list have+the same index, the value at that index is implementation-dependent.+(In GHC, the last value specified for that index is used.+Other implementations will also do this for unboxed arrays, but Haskell+98 requires that for 'Array' the value at such indices is bottom.)++Because the indices must be checked for these errors, 'array' is+strict in the bounds argument and in the indices of the association+list.  Whether @array@ is strict or non-strict in the elements depends+on the array type: 'Data.Array.Array' is a non-strict array type, but+all of the 'Data.Array.Unboxed.UArray' arrays are strict.  Thus in a+non-strict array, recurrences such as the following are possible:++> a = array (1,100) ((1,1) : [(i, i * a!(i-1)) | i \<- [2..100]])++Not every index within the bounds of the array need appear in the+association list, but the values associated with indices that do not+appear will be undefined.++If, in any dimension, the lower bound is greater than the upper bound,+then the array is legal, but empty. Indexing an empty array always+gives an array-bounds error, but 'bounds' still yields the bounds with+which the array was constructed.+-}+array   :: (IArray a e, Ix i)+        => (i,i)        -- ^ bounds of the array: (lowest,highest)+        -> [(i, e)]     -- ^ list of associations+        -> a i e+array (l,u) ies = unsafeArray (l,u) [(index (l,u) i, e) | (i, e) <- ies]++-- Since unsafeFreeze is not guaranteed to be only a cast, we will+-- use unsafeArray and zip instead of a specialized loop to implement+-- listArray, unlike Array.listArray, even though it generates some+-- unnecessary heap allocation. Will use the loop only when we have+-- fast unsafeFreeze, namely for Array and UArray (well, they cover+-- almost all cases).++{-# INLINE listArray #-}+-- | Constructs an immutable array from a list of initial elements.+-- The list gives the elements of the array in ascending order+-- beginning with the lowest index.+listArray :: (IArray a e, Ix i) => (i,i) -> [e] -> a i e+listArray (l,u) es = unsafeArray (l,u) (zip [0 .. rangeSize (l,u) - 1] es)++{-# INLINE (!) #-}+-- | Returns the element of an immutable array at the specified index.+(!) :: (IArray a e, Ix i) => a i e -> i -> e+arr ! i = case bounds arr of (l,u) -> unsafeAt arr (index (l,u) i)++{-# INLINE indices #-}+-- | Returns a list of all the valid indices in an array.+indices :: (HasBounds a, Ix i) => a i e -> [i]+indices arr = case bounds arr of (l,u) -> range (l,u)++{-# INLINE elems #-}+-- | Returns a list of all the elements of an array, in the same order+-- as their indices.+elems :: (IArray a e, Ix i) => a i e -> [e]+elems arr = case bounds arr of+    (l,u) -> [unsafeAt arr i | i <- [0 .. rangeSize (l,u) - 1]]++{-# INLINE assocs #-}+-- | Returns the contents of an array as a list of associations.+assocs :: (IArray a e, Ix i) => a i e -> [(i, e)]+assocs arr = case bounds arr of+    (l,u) -> [(i, unsafeAt arr (unsafeIndex (l,u) i)) | i <- range (l,u)]++{-# INLINE accumArray #-}+{-|+Constructs an immutable array from a list of associations.  Unlike+'array', the same index is allowed to occur multiple times in the list+of associations; an /accumulating function/ is used to combine the+values of elements with the same index.++For example, given a list of values of some index type, hist produces+a histogram of the number of occurrences of each index within a+specified range:++> hist :: (Ix a, Num b) => (a,a) -> [a] -> Array a b+> hist bnds is = accumArray (+) 0 bnds [(i, 1) | i\<-is, inRange bnds i]+-}+accumArray :: (IArray a e, Ix i)+        => (e -> e' -> e)       -- ^ An accumulating function+        -> e                    -- ^ A default element+        -> (i,i)                -- ^ The bounds of the array+        -> [(i, e')]            -- ^ List of associations+        -> a i e                -- ^ Returns: the array+accumArray f init (l,u) ies =+    unsafeAccumArray f init (l,u) [(index (l,u) i, e) | (i, e) <- ies]++{-# INLINE (//) #-}+{-|+Takes an array and a list of pairs and returns an array identical to+the left argument except that it has been updated by the associations+in the right argument.  For example, if m is a 1-origin, n by n matrix,+then @m\/\/[((i,i), 0) | i \<- [1..n]]@ is the same matrix, except with+the diagonal zeroed.++As with the 'array' function, if any two associations in the list have+the same index, the value at that index is implementation-dependent.+(In GHC, the last value specified for that index is used.+Other implementations will also do this for unboxed arrays, but Haskell+98 requires that for 'Array' the value at such indices is bottom.)++For most array types, this operation is O(/n/) where /n/ is the size+of the array.  However, the 'Data.Array.Diff.DiffArray' type provides+this operation with complexity linear in the number of updates.+-}+(//) :: (IArray a e, Ix i) => a i e -> [(i, e)] -> a i e+arr // ies = case bounds arr of+    (l,u) -> unsafeReplace arr [(index (l,u) i, e) | (i, e) <- ies]++{-# INLINE accum #-}+{-|+@accum f@ takes an array and an association list and accumulates pairs+from the list into the array with the accumulating function @f@. Thus+'accumArray' can be defined using 'accum':++> accumArray f z b = accum f (array b [(i, z) | i \<- range b])+-}+accum :: (IArray a e, Ix i) => (e -> e' -> e) -> a i e -> [(i, e')] -> a i e+accum f arr ies = case bounds arr of+    (l,u) -> unsafeAccum f arr [(index (l,u) i, e) | (i, e) <- ies]++{-# INLINE amap #-}+-- | Returns a new array derived from the original array by applying a+-- function to each of the elements.+amap :: (IArray a e', IArray a e, Ix i) => (e' -> e) -> a i e' -> a i e+amap f arr = case bounds arr of+    (l,u) -> unsafeArray (l,u) [(i, f (unsafeAt arr i))+                               | i <- [0 .. rangeSize (l,u) - 1]]+{-# INLINE ixmap #-}+-- | Returns a new array derived from the original array by applying a+-- function to each of the indices.+ixmap :: (IArray a e, Ix i, Ix j) => (i,i) -> (i -> j) -> a j e -> a i e+ixmap (l,u) f arr =+    unsafeArray (l,u) [(unsafeIndex (l,u) i, arr ! f i) | i <- range (l,u)]++-----------------------------------------------------------------------------+-- Implementation of Show instance++{-# SPECIALISE+    showsIArray :: (IArray a e, Ix i, Show i, Show e) =>+                   Int -> a i e -> ShowS+  #-}++showsIArray :: (IArray a e, Ix i, Show i, Show e) => Int -> a i e -> ShowS+showsIArray p a =+    showParen (p > 9) $+    showString "array " .+    shows (bounds a) .+    showChar ' ' .+    shows (assocs a)++-----------------------------------------------------------------------------+-- Implementation of Eq/Ord instances++{-# INLINE eqIArray #-}+eqIArray :: (IArray a e, Ix i, Eq e) => a i e -> a i e -> Bool+eqIArray arr1 arr2 =+    case bounds arr1 of { (l1,u1) ->+    case bounds arr2 of { (l2,u2) ->+    if rangeSize (l1,u1) == 0+      then rangeSize (l2,u2) == 0+      else l1 == l2 && u1 == u2 &&+           and [ unsafeAt arr1 i == unsafeAt arr2 i+               | i <- [0 .. rangeSize (l1,u1) - 1]]}}++{-# INLINE cmpIArray #-}+cmpIArray :: (IArray a e, Ix i, Ord e) => a i e -> a i e -> Ordering+cmpIArray arr1 arr2 = compare (assocs arr1) (assocs arr2)++{-# INLINE cmpIntIArray #-}+cmpIntIArray :: (IArray a e, Ord e) => a Int e -> a Int e -> Ordering+cmpIntIArray arr1 arr2 =+    case bounds arr1 of { (l1,u1) ->+    case bounds arr2 of { (l2,u2) ->+    if rangeSize (l1,u1) == 0 then if rangeSize (l2,u2) == 0 then EQ else LT else+    if rangeSize (l2,u2) == 0 then GT else+    case compare l1 l2 of+        EQ    -> foldr cmp (compare u1 u2) [0 .. rangeSize (l1, min u1 u2) - 1]+        other -> other } }+    where+    cmp i rest = case compare (unsafeAt arr1 i) (unsafeAt arr2 i) of+        EQ    -> rest+        other -> other++{-# RULES "cmpIArray/Int" cmpIArray = cmpIntIArray #-}+
+ Data/ArrayBZ/Internals/MArray.hs view
@@ -0,0 +1,276 @@+{-# LANGUAGE CPP, MultiParamTypeClasses #-}+{- |+   Module     : Data.ArrayBZ.Internals.MArray+   Copyright  : (c) The University of Glasgow 2001 & (c) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: GHC/Hugs++Mutable arrays: class and general algorithms+Freeze/Thaw: mutable<->immutable arrays conversion++-}++module Data.ArrayBZ.Internals.MArray where++import Control.Monad.ST         ( ST, runST )+import Data.Ix+#ifdef __GLASGOW_HASKELL__+import GHC.Arr                  ( unsafeIndex )+#endif+#ifdef __HUGS__+import Hugs.Array               ( unsafeIndex )+#endif++import Data.ArrayBZ.Internals.IArray++-----------------------------------------------------------------------------+-- Mutable arrays++-- | Value used to initialize undefined array elements+{-# NOINLINE arrEleBottom #-}+arrEleBottom :: a+arrEleBottom = error "MArray: undefined array element"++-- | Class of array types with mutable bounds+class (Monad m) => HasMutableBounds a m where+    -- | Get the current bounds of an array+    getBounds :: Ix i => a i e -> m (i,i)++{-| Class of mutable array types.++An array type has the form @(a i e)@ where @a@ is the array type+constructor (kind @* -> * -> *@), @i@ is the index type (a member of+the class 'Ix'), and @e@ is the element type.++The @MArray@ class is parameterised over both @a@ and @e@ (so that+instances specialised to certain element types can be defined, in the+same way as for 'IArray'), and also over the type of the monad, @m@,+in which the mutable array will be manipulated.+-}+class (Monad m, HasMutableBounds a m) => MArray a e m where++    -- | Builds a new array, with every element initialised to the supplied+    -- value.+    newArray    :: Ix i => (i,i) -> e -> m (a i e)++    -- | Builds a new array, with every element initialised to undefined.+    newArray_   :: Ix i => (i,i) -> m (a i e)++    unsafeRead  :: Ix i => a i e -> Int -> m e+    unsafeWrite :: Ix i => a i e -> Int -> e -> m ()++    readArray   :: Ix i => a i e -> i -> m e+    writeArray  :: Ix i => a i e -> i -> e -> m ()++    {-# INLINE newArray #-}+        -- The INLINE is crucial, because until we know at least which monad+        -- we are in, the code below allocates like crazy.  So inline it,+        -- in the hope that the context will know the monad.+    newArray (l,u) init = do+        marr <- newArray_ (l,u)+        sequence_ [unsafeWrite marr i init | i <- [0 .. rangeSize (l,u) - 1]]+        return marr++    newArray_ (l,u) = newArray (l,u) arrEleBottom++    -- newArray takes an initialiser which all elements of+    -- the newly created array are initialised to.  newArray_ takes+    -- no initialiser, it is assumed that the array is initialised with+    -- "undefined" values.++    -- why not omit newArray_?  Because in the unboxed array case we would+    -- like to omit the initialisation altogether if possible.  We can't do+    -- this for boxed arrays, because the elements must all have valid values+    -- at all times in case of garbage collection.++    -- why not omit newArray?  Because in the boxed case, we can omit the+    -- default initialisation with undefined values if we *do* know the+    -- initial value and it is constant for all elements.++    {-# INLINE readArray #-}+    -- | Read an element from a mutable array+    readArray marr i = do+        (l,u) <- getBounds marr+        unsafeRead marr (index (l,u) i)++    {-# INLINE writeArray #-}+    -- | Write an element in a mutable array+    writeArray marr i e = do+        (l,u) <- getBounds marr+        unsafeWrite marr (index (l,u) i) e+++-----------------------------------------------------------------------------+-- Algorithms on mutable arrays++{-# INLINE newListArray #-}+-- | Constructs a mutable array from a list of initial elements.+-- The list gives the elements of the array in ascending order+-- beginning with the lowest index.+newListArray :: (MArray a e m, Ix i) => (i,i) -> [e] -> m (a i e)+newListArray (l,u) es = do+    marr <- newArray_ (l,u)+    let n = rangeSize (l,u)+    let fillFromList i xs | i == n    = return ()+                          | otherwise = case xs of+            []   -> return ()+            y:ys -> unsafeWrite marr i y >> fillFromList (i+1) ys+    fillFromList 0 es+    return marr++{-# INLINE getIndices #-}+-- | Return a list of all the indexes of a mutable array+getIndices :: (MArray a e m, Ix i) => a i e -> m [i]+getIndices marr = do+    (l,u) <- getBounds marr+    return (range (l,u))++{-# INLINE getElems #-}+-- | Return a list of all the elements of a mutable array+getElems :: (MArray a e m, Ix i) => a i e -> m [e]+getElems marr = do+    (l,u) <- getBounds marr+    sequence [unsafeRead marr i | i <- [0 .. rangeSize (l,u) - 1]]++{-# INLINE getAssocs #-}+-- | Return a list of all the associations of a mutable array, in+-- index order.+getAssocs :: (MArray a e m, Ix i) => a i e -> m [(i, e)]+getAssocs marr = do+    (l,u) <- getBounds marr+    sequence [ do e <- unsafeRead marr (index (l,u) i); return (i,e)+             | i <- range (l,u)]++{-# INLINE mapArray #-}+-- | Constructs a new array derived from the original array by applying a+-- function to each of the elements.+mapArray :: (MArray a e' m, MArray a e m, Ix i) => (e' -> e) -> a i e' -> m (a i e)+mapArray f marr = do+    (l,u) <- getBounds marr+    marr' <- newArray_ (l,u)+    sequence_ [do+        e <- unsafeRead marr i+        unsafeWrite marr' i (f e)+        | i <- [0 .. rangeSize (l,u) - 1]]+    return marr'++{-# INLINE mapIndices #-}+-- | Constructs a new array derived from the original array by applying a+-- function to each of the indices.+mapIndices :: (MArray a e m, Ix i, Ix j) => (i,i) -> (i -> j) -> a j e -> m (a i e)+mapIndices (l,u) f marr = do+    marr' <- newArray_ (l,u)+    sequence_ [do+        e <- readArray marr (f i)+        unsafeWrite marr' (unsafeIndex (l,u) i) e+        | i <- range (l,u)]+    return marr'++-----------------------------------------------------------------------------+-- Freezing++-- | Converts a mutable array (any instance of 'MArray') to an+-- immutable array (any instance of 'IArray') by taking a complete+-- copy of it.+freeze :: (Ix i, MArray a e m, IArray b e) => a i e -> m (b i e)+freeze marr = do+    (l,u) <- getBounds marr+    ies <- sequence [do e <- unsafeRead marr i; return (i,e)+                     | i <- [0 .. rangeSize (l,u) - 1]]+    return (unsafeArray (l,u) ies)++-- In-place conversion of mutable arrays to immutable ones places+-- a proof obligation on the user: no other parts of your code can+-- have a reference to the array at the point where you unsafely+-- freeze it (and, subsequently mutate it, I suspect).++{- |+   Converts an mutable array into an immutable array.  The+   implementation may either simply cast the array from+   one type to the other without copying the array, or it+   may take a full copy of the array.++   Note that because the array is possibly not copied, any subsequent+   modifications made to the mutable version of the array may be+   shared with the immutable version.  It is safe to use, therefore, if+   the mutable version is never modified after the freeze operation.++   The non-copying implementation is supported between certain pairs+   of array types only; one constraint is that the array types must+   have identical representations.  In GHC, The following pairs of+   array types have a non-copying O(1) implementation of+   'unsafeFreeze'.  Because the optimised versions are enabled by+   specialisations, you will need to compile with optimisation (-O) to+   get them.++     * 'Data.Array.IO.IOUArray' -> 'Data.Array.Unboxed.UArray'++     * 'Data.Array.ST.STUArray' -> 'Data.Array.Unboxed.UArray'++     * 'Data.Array.IO.IOArray' -> 'Data.Array.Array'++     * 'Data.Array.ST.STArray' -> 'Data.Array.Array'+-}+{-# INLINE unsafeFreeze #-}+unsafeFreeze :: (Ix i, MArray a e m, IArray b e) => a i e -> m (b i e)+unsafeFreeze = freeze++-----------------------------------------------------------------------------+-- Thawing++-- | Converts an immutable array (any instance of 'IArray') into a+-- mutable array (any instance of 'MArray') by taking a complete copy+-- of it.+thaw :: (Ix i, IArray a e, MArray b e m) => a i e -> m (b i e)+thaw arr = case bounds arr of+  (l,u) -> do+    marr <- newArray_ (l,u)+    sequence_ [unsafeWrite marr i (unsafeAt arr i)+               | i <- [0 .. rangeSize (l,u) - 1]]+    return marr++-- In-place conversion of immutable arrays to mutable ones places+-- a proof obligation on the user: no other parts of your code can+-- have a reference to the array at the point where you unsafely+-- thaw it (and, subsequently mutate it, I suspect).++{- |+   Converts an immutable array into a mutable array.  The+   implementation may either simply cast the array from+   one type to the other without copying the array, or it+   may take a full copy of the array.++   Note that because the array is possibly not copied, any subsequent+   modifications made to the mutable version of the array may be+   shared with the immutable version.  It is only safe to use,+   therefore, if the immutable array is never referenced again in this+   thread, and there is no possibility that it can be also referenced+   in another thread.  If you use an unsafeThaw/write/unsafeFreeze+   sequence in a multi-threaded setting, then you must ensure that+   this sequence is atomic with respect to other threads, or a garbage+   collector crash may result (because the write may be writing to a+   frozen array).++   The non-copying implementation is supported between certain pairs+   of array types only; one constraint is that the array types must+   have identical representations.  In GHC, The following pairs of+   array types have a non-copying O(1) implementation of+   'unsafeThaw'.  Because the optimised versions are enabled by+   specialisations, you will need to compile with optimisation (-O) to+   get them.++     * 'Data.Array.Unboxed.UArray' -> 'Data.Array.IO.IOUArray'++     * 'Data.Array.Unboxed.UArray' -> 'Data.Array.ST.STUArray'++     * 'Data.Array.Array'  -> 'Data.Array.IO.IOArray'++     * 'Data.Array.Array'  -> 'Data.Array.ST.STArray'+-}+{-# INLINE unsafeThaw #-}+unsafeThaw :: (Ix i, IArray a e, MArray b e m) => a i e -> m (b i e)+unsafeThaw = thaw+
+ Data/ArrayBZ/Internals/Unboxed.hs view
@@ -0,0 +1,247 @@+{-# LANGUAGE CPP, ScopedTypeVariables, FlexibleInstances, TypeSynonymInstances,+  MultiParamTypeClasses #-}+{- |+   Module     : Data.ArrayBZ.Internals.Unboxed+   Copyright  : (c) The University of Glasgow 2001 & (c) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: GHC/Hugs++Unboxed arrays++Based on the idea of Oleg Kiselyov+  (see http://www.haskell.org/pipermail/haskell-cafe/2004-July/006400.html)+-}++module Data.ArrayBZ.Internals.Unboxed where++import Control.Monad.ST         (ST, runST)+import Control.Monad.ST.Lazy    ( strictToLazyST )+import qualified Control.Monad.ST.Lazy as Lazy (ST)+import Data.Ix+import Data.Typeable+#include "Typeable.h"++import Control.Monad.STorIO+import Data.ArrayBZ.Internals.IArray+import Data.ArrayBZ.Internals.MArray+import Data.HasDefaultValue+import Data.Unboxed++-- ---------------------------------------------------------------------------+-- | Unboxed mutable arrays++data UnboxedMutableArray s i e  =  UMA !i !i !(MUVec s e)++instance HasBounds (UnboxedMutableArray s) where+    {-# INLINE bounds #-}+    bounds (UMA l u _) = (l,u)++instance (STorIO m s) => HasMutableBounds (UnboxedMutableArray s) m where+    {-# INLINE getBounds #-}+    getBounds (UMA l u _) = return (l,u)++instance (STorIO m s, Unboxed e) => MArray (UnboxedMutableArray s) e m where+    newArray_ (l,u) = do arr <- allocUnboxed (rangeSize (l,u))+                         return (UMA l u arr)+    {-# INLINE unsafeRead #-}+    unsafeRead  (UMA _ _ arr) index  =  readUnboxed  arr index+    {-# INLINE unsafeWrite #-}+    unsafeWrite (UMA _ _ arr) index  =  writeUnboxed arr index++-- ---------------------------------------------------------------------------+-- | Unboxed mutable arrays in ST monad++type STUArray = UnboxedMutableArray++INSTANCE_TYPEABLE3(STUArray,stUArrayTc,"STUArray")++-- ---------------------------------------------------------------------------+-- STUArray also works in Lazy ST monad++instance (Unboxed e) => MArray (STUArray s) e (Lazy.ST s) where+    {-# INLINE newArray_ #-}+    newArray_   (l,u)   = strictToLazyST (newArray_ (l,u))+    {-# INLINE unsafeRead #-}+    unsafeRead  arr i   = strictToLazyST (unsafeRead  arr i)+    {-# INLINE unsafeWrite #-}+    unsafeWrite arr i e = strictToLazyST (unsafeWrite arr i e)++-- ---------------------------------------------------------------------------+-- | Unboxed mutable arrays in IO monad++type IOUArray = IOSpecific3 UnboxedMutableArray++INSTANCE_TYPEABLE2(IOUArray,iOUArrayTc,"IOUArray")++-- ---------------------------------------------------------------------------+-- | Unboxed arrays++data UArray i e  =  UA !i !i !(UVec e)++INSTANCE_TYPEABLE2(UArray,uArrayTc,"UArray")++instance HasBounds UArray where+    {-# INLINE bounds #-}+    bounds (UA l u _) = (l,u)++instance (Unboxed e, HasDefaultValue e) => IArray UArray e where+    {-# INLINE unsafeArray #-}+    -- Create new array filled with (i,e) values+    unsafeArray lu ies = runST (withNewArray lu defaultValue (doReplace ies))+    {-# INLINE unsafeAt #-}+    unsafeAt (UA _ _ arr) index = indexUnboxed arr index+    {-# INLINE unsafeReplace #-}+    -- Make a copy of array and perform (i,e) replacements+    unsafeReplace arr ies = runST (withArrayCopy arr (doReplace ies))+    {-# INLINE unsafeAccum #-}+    -- Make a copy of array and perform (i,e) accumulation in new array+    unsafeAccum f arr ies = runST (withArrayCopy arr (doAccum f ies))+    {-# INLINE unsafeAccumArray #-}+    -- Create new array accumulating (i,e) values+    unsafeAccumArray f init lu ies = runST (withNewArray lu init (doAccum f ies))+++-- Implementation helper functions -------------++-- Create new array and perform given action on it before freezing+withNewArray lu init action = do+    marr <- newArray lu init+    action marr+    unsafeFreezeUA marr++-- Make a copy of array and perform given action on it before freezing+withArrayCopy arr action = do+    marr <- thawUA arr+    action marr+    unsafeFreezeUA marr++-- Perform (i,e) replaces in mutable array+doReplace ies marr = do+    sequence_ [unsafeWrite marr i e | (i, e) <- ies]++-- Accumulate (i,e) values in mutable array+doAccum f ies marr = do+    sequence_ [do old <- unsafeRead marr i+                  unsafeWrite marr i (f old new)+              | (i, new) <- ies]++-- Mutable->immutable array conversion which takes a copy of contents+freezeUA uma@(UMA l u marr) = do+    arr <- freezeUnboxed marr (sizeOfUMA uma)+    return (UA l u arr)++-- Immutable->mutable array conversion which takes a copy of contents+thawUA ua@(UA l u arr) = do+    marr <- thawUnboxed arr (sizeOfUA ua)+    return (UMA l u marr)++-- On-the-place mutable->immutable array conversion+unsafeFreezeUA (UMA l u marr) = do+    arr <- unsafeFreezeUnboxed marr+    return (UA l u arr)++-- On-the-place immutable->mutable array conversion+unsafeThawUA ua@(UA l u arr) = do+    marr <- unsafeThawUnboxed arr+    return (UMA l u marr)++-- | Array size in bytes+sizeOfUA :: forall i e. (Ix i, Unboxed e) => UArray i e -> Int+sizeOfUA  arr =+     rangeSize (bounds arr) * sizeOfUnboxed (undefined :: e)++sizeOfUMA :: forall i e s. (Ix i, Unboxed e) => UnboxedMutableArray s i e -> Int+sizeOfUMA marr =+    rangeSize (bounds marr) * sizeOfUnboxed (undefined :: e)++-- ---------------------------------------------------------------------------+-- | Freeze/thaw rules for IOUArray++freezeIOUArray       :: (Unboxed e, HasDefaultValue e, Ix i) => IOUArray i e -> IO (UArray i e)+thawIOUArray         :: (Unboxed e, HasDefaultValue e, Ix i) => UArray i e -> IO (IOUArray i e)+unsafeFreezeIOUArray :: (Unboxed e, HasDefaultValue e, Ix i) => IOUArray i e -> IO (UArray i e)+unsafeThawIOUArray   :: (Unboxed e, HasDefaultValue e, Ix i) => UArray i e -> IO (IOUArray i e)++freezeIOUArray       = freezeUA+thawIOUArray         = thawUA+unsafeFreezeIOUArray = unsafeFreezeUA+unsafeThawIOUArray   = unsafeThawUA++{-# RULES+"freeze/IOUArray" forall (x :: (forall s e i . (Unboxed e, HasDefaultValue e) => IOUArray i e)) . freeze x = freezeIOUArray x+"thaw/IOUArray"   forall (x :: (forall   e i . (Unboxed e, HasDefaultValue e) =>   UArray i e)) . thaw   x = thawIOUArray   x+"unsafeFreeze/IOUArray" forall (x :: (forall s e i . (Unboxed e, HasDefaultValue e) => IOUArray i e)) . unsafeFreeze x = unsafeFreezeIOUArray x+"unsafeThaw/IOUArray"   forall (x :: (forall   e i . (Unboxed e, HasDefaultValue e) =>   UArray i e)) . unsafeThaw   x = unsafeThawIOUArray   x+    #-}++-- ---------------------------------------------------------------------------+-- | Freeze/thaw rules for STUArray++freezeSTUArray       :: (Unboxed e, HasDefaultValue e, Ix i) => STUArray s i e -> ST s (UArray i e)+thawSTUArray         :: (Unboxed e, HasDefaultValue e, Ix i) => UArray i e -> ST s (STUArray s i e)+unsafeFreezeSTUArray :: (Unboxed e, HasDefaultValue e, Ix i) => STUArray s i e -> ST s (UArray i e)+unsafeThawSTUArray   :: (Unboxed e, HasDefaultValue e, Ix i) => UArray i e -> ST s (STUArray s i e)++freezeSTUArray       = freezeUA+thawSTUArray         = thawUA+unsafeFreezeSTUArray = unsafeFreezeUA+unsafeThawSTUArray   = unsafeThawUA++{-# RULES+"freeze/STUArray" forall (x :: (forall s e i . (Unboxed e, HasDefaultValue e) => STUArray s i e)) . freeze x = freezeSTUArray x+"thaw/STUArray"   forall (x :: (forall   e i . (Unboxed e, HasDefaultValue e) =>   UArray   i e)) . thaw   x = thawSTUArray   x+"unsafeFreeze/STUArray" forall (x :: (forall s e i . (Unboxed e, HasDefaultValue e) => STUArray s i e)) . unsafeFreeze x = unsafeFreezeSTUArray x+"unsafeThaw/STUArray"   forall (x :: (forall   e i . (Unboxed e, HasDefaultValue e) =>   UArray   i e)) . unsafeThaw   x = unsafeThawSTUArray   x+    #-}++-- ---------------------------------------------------------------------------+-- | Casts to arrays with different element type++-- | Casts an 'UArray' with one element type into 'UArray' with a+-- different element type. All the elements of the resulting array+-- are undefined (unless you know what you\'re doing...).+-- Upper array bound is recalculated according to elements size,+-- for example UArray (1,2) Word32 -> UArray (1,8) Word8+castUArray :: forall i e e'. (Ix i, Enum i, Unboxed e, Unboxed e')+           => UArray i e -> UArray i e'+castUArray (UA l u vec) =+    (UA l u' (castUnboxed vec))+        where u' = toEnum (fromEnum l - 1 + newSize)+              newSize = rangeSize (l,u)   *   sizeOfUnboxed (undefined::e)+                                        `div` sizeOfUnboxed (undefined::e')++-- | Casts an 'IOUArray' with one element type into 'IOUArray' with a different+-- element type (upper bound is recalculated).+castIOUArray :: forall i e e'. (Ix i, Enum i, Unboxed e, Unboxed e')+             => IOUArray i e -> IOUArray i e'+castIOUArray (UMA l u mvec) =+    (UMA l u' (castMUnboxed mvec))+        where u' = toEnum (fromEnum l - 1 + newSize)+              newSize = rangeSize (l,u)   *   sizeOfUnboxed (undefined::e)+                                        `div` sizeOfUnboxed (undefined::e')++-- | Casts an 'STUArray' with one element type into 'STUArray' with a different+-- element type (upper bound is recalculated).+castSTUArray :: forall i e e' s. (Ix i, Enum i, Unboxed e, Unboxed e')+             => STUArray s i e -> STUArray s i e'+castSTUArray (UMA l u mvec) =+    (UMA l u' (castMUnboxed mvec))+        where u' = toEnum (fromEnum l - 1 + newSize)+              newSize = rangeSize (l,u)   *   sizeOfUnboxed (undefined::e)+                                        `div` sizeOfUnboxed (undefined::e')++-- ---------------------------------------------------------------------------+-- | Instances++instance (Ix i, Show i, Show e, Unboxed e, HasDefaultValue e) => Show (UArray i e) where+    showsPrec = showsIArray++instance (Ix i, Eq i, Eq e, Unboxed e, HasDefaultValue e) => Eq (UArray i e) where+    (==) = eqIArray++instance (Ix i, Ord i, Ord e, Unboxed e, HasDefaultValue e) => Ord (UArray i e) where+    compare = cmpIArray+
+ Data/ArrayBZ/Internals/readme.txt view
@@ -0,0 +1,21 @@+Module hierarchy:++Module Data.ArrayBZ.Internals.MArray defines class MArray and general algorithms+working with any instance of this class++Module Data.ArrayBZ.Internals.IArray defines class IArray and general algorithms+working with any instance of this class. In addition, it defines functions+used to implement Show, Eq and Ord instances (these instances cannot be+defined here due to the "overlapped instances" problem)++Module Data.ArrayBZ.Internals.Boxed imports modules IArray and MArray, and then+defines Array/IOArray/STArray. Module Data.ArrayBZ.Internals.Unboxed also imports+modules IArray and MArray, and then defines UArray/IOUArray/STUArray++Modules Data.ArrayBZ.Boxed and Data.ArrayBZ.Unboxed reexports corresponding+internal modules together with IArray and MArray modules, what gives their users+ability to use all boxed (unboxed) arrays together with all general algorithms+defined for IArray and MArray classes++Also, file unused.hs contains parts of original code that's still not used in+new one
+ Data/ArrayBZ/Internals/unused.hs view
@@ -0,0 +1,137 @@++This file contains remaining code from old Data.Array.* library that is still+unused in new code. It mainly consists of speed tricks (that may be even not+needed in new code).++------------------------------------------------------------------------------------------+class HasBounds a => IArray a e where+    unsafeReplace arr ies = runST (unsafeReplaceST arr ies >>= unsafeFreeze)+    unsafeAccum f arr ies = runST (unsafeAccumST f arr ies >>= unsafeFreeze)+    unsafeAccumArray f e lu ies = runST (unsafeAccumArrayST f e lu ies >>= unsafeFreeze)++{-# INLINE unsafeReplaceST #-}+unsafeReplaceST :: (IArray a e, Ix i) => a i e -> [(Int, e)] -> ST s (STArray s i e)+unsafeReplaceST arr ies = do+    marr <- thaw arr+    sequence_ [unsafeWrite marr i e | (i, e) <- ies]+    return marr++{-# INLINE unsafeAccumST #-}+unsafeAccumST :: (IArray a e, Ix i) => (e -> e' -> e) -> a i e -> [(Int, e')] -> ST s (STArray s i e)+unsafeAccumST f arr ies = do+    marr <- thaw arr+    sequence_ [do+        old <- unsafeRead marr i+        unsafeWrite marr i (f old new)+        | (i, new) <- ies]+    return marr++{-# INLINE unsafeAccumArrayST #-}+unsafeAccumArrayST :: Ix i => (e -> e' -> e) -> e -> (i,i) -> [(Int, e')] -> ST s (STArray s i e)+unsafeAccumArrayST f e (l,u) ies = do+    marr <- newArray (l,u) e+    sequence_ [do+        old <- unsafeRead marr i+        unsafeWrite marr i (f old new)+        | (i, new) <- ies]+    return marr++------------------------------------------------------------------------------------------+{-# INLINE listArrayST #-}+listArrayST :: Ix i => (i,i) -> [e] -> ST s (STArray s i e)+listArrayST (l,u) es = do+    marr <- newArray_ (l,u)+    let n = rangeSize (l,u)+    let fillFromList i xs | i == n    = return ()+                          | otherwise = case xs of+            []   -> return ()+            y:ys -> unsafeWrite marr i y >> fillFromList (i+1) ys+    fillFromList 0 es+    return marr++{-# RULES+"listArray/Array" listArray =+    \lu es -> runST (listArrayST lu es >>= ArrST.unsafeFreezeSTArray)+    #-}++{-# INLINE listUArrayST #-}+listUArrayST :: (MArray (STUArray s) e (ST s), Ix i)+             => (i,i) -> [e] -> ST s (STUArray s i e)+listUArrayST (l,u) es = do+    marr <- newArray_ (l,u)+    let n = rangeSize (l,u)+    let fillFromList i xs | i == n    = return ()+                          | otherwise = case xs of+            []   -> return ()+            y:ys -> unsafeWrite marr i y >> fillFromList (i+1) ys+    fillFromList 0 es+    return marr++-- I don't know how to write a single rule for listUArrayST, because+-- the type looks like constrained over 's', which runST doesn't+-- like. In fact all MArray (STUArray s) instances are polymorphic+-- wrt. 's', but runST can't know that.+--+-- More precisely, we'd like to write this:+--   listUArray :: (forall s. MArray (STUArray s) e (ST s), Ix i)+--              => (i,i) -> [e] -> UArray i e+--   listUArray lu = runST (listUArrayST lu es >>= unsafeFreezeSTUArray)+--   {-# RULES listArray = listUArray+-- Then we could call listUArray at any type 'e' that had a suitable+-- MArray instance.  But sadly we can't, because we don't have quantified+-- constraints.  Hence the mass of rules below.++-- I would like also to write a rule for listUArrayST (or listArray or+-- whatever) applied to unpackCString#. Unfortunately unpackCString#+-- calls seem to be floated out, then floated back into the middle+-- of listUArrayST, so I was not able to do this.++#ifdef __GLASGOW_HASKELL__+type ListUArray e = forall i . Ix i => (i,i) -> [e] -> UArray i e++{-# RULES+"listArray/UArray/Bool"      listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray Bool+"listArray/UArray/Char"      listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray Char+"listArray/UArray/Int"       listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray Int+"listArray/UArray/Word"      listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray Word+"listArray/UArray/Ptr"       listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray (Ptr a)+"listArray/UArray/FunPtr"    listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray (FunPtr a)+"listArray/UArray/Float"     listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray Float+"listArray/UArray/Double"    listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray Double+"listArray/UArray/StablePtr" listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray (StablePtr a)+"listArray/UArray/Int8"      listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray Int8+"listArray/UArray/Int16"     listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray Int16+"listArray/UArray/Int32"     listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray Int32+"listArray/UArray/Int64"     listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray Int64+"listArray/UArray/Word8"     listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray Word8+"listArray/UArray/Word16"    listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray Word16+"listArray/UArray/Word32"    listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray Word32+"listArray/UArray/Word64"    listArray+   = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray Word64+    #-}+#endif++------------------------------------------------------------------------------------------+instance MArray (STArray s) e (Lazy.ST s) where+    {-# INLINE newArray #-}+    newArray (l,u) e    = strictToLazyST (ArrST.newSTArray (l,u) e)+    {-# INLINE unsafeRead #-}+    unsafeRead arr i    = strictToLazyST (ArrST.unsafeReadSTArray arr i)+    {-# INLINE unsafeWrite #-}+    unsafeWrite arr i e = strictToLazyST (ArrST.unsafeWriteSTArray arr i e)
+ Data/ArrayBZ/MArray.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE CPP #-}+{- |+   Module     : Data.ArrayBZ.MArray+   Copyright  : (c) The University of Glasgow 2001 & (c) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: Hugs/GHC++An overloaded interface to mutable arrays.  For array types which can be+used with this interface, see "Data.ArrayBZ.IO", "Data.ArrayBZ.ST",+and "Data.ArrayBZ.Storable".++-}++module Data.ArrayBZ.MArray (+    -- * Class of mutable array types+    MArray,       -- :: (* -> * -> *) -> * -> (* -> *) -> class++    -- * Class of array types with bounds+    HasBounds,    -- :: (* -> * -> *) -> class++    -- * Class of array types with mutable bounds+    HasMutableBounds,    -- :: (* -> * -> *) -> (* -> *) -> class++    -- * The @Ix@ class and operations+    module Data.Ix,++    -- * Constructing mutable arrays+    newArray,     -- :: (MArray a e m, Ix i) => (i,i) -> e -> m (a i e)+    newArray_,    -- :: (MArray a e m, Ix i) => (i,i) -> m (a i e)+    newListArray, -- :: (MArray a e m, Ix i) => (i,i) -> [e] -> m (a i e)++    -- * Reading and writing mutable arrays+    readArray,    -- :: (MArray a e m, Ix i) => a i e -> i -> m e+    writeArray,   -- :: (MArray a e m, Ix i) => a i e -> i -> e -> m ()++    -- * Derived arrays+    mapArray,     -- :: (MArray a e' m, MArray a e m, Ix i) => (e' -> e) -> a i e' -> m (a i e)+    mapIndices,   -- :: (MArray a e m, Ix i, Ix j) => (i,i) -> (i -> j) -> a j e -> m (a i e)++    -- * Deconstructing mutable arrays+    bounds,       -- :: (HasBounds a, Ix i) => a i e -> (i,i)+    indices,      -- :: (HasBounds a, Ix i) => a i e -> [i]+    getBounds,    -- :: (HasMutableBounds a, Ix i) => a i e -> m (i,i)+    getIndices,   -- :: (HasMutableBounds a, Ix i) => a i e -> m [i]+    getElems,     -- :: (MArray a e m, Ix i) => a i e -> m [e]+    getAssocs,    -- :: (MArray a e m, Ix i) => a i e -> m [(i, e)]++    -- * Conversions between mutable and immutable arrays+    freeze,       -- :: (Ix i, MArray a e m, IArray b e) => a i e -> m (b i e)+    unsafeFreeze, -- :: (Ix i, MArray a e m, IArray b e) => a i e -> m (b i e)+    thaw,         -- :: (Ix i, IArray a e, MArray b e m) => a i e -> m (b i e)+    unsafeThaw,   -- :: (Ix i, IArray a e, MArray b e m) => a i e -> m (b i e)+  ) where++import Data.Ix++import Data.ArrayBZ.Internals.IArray+import Data.ArrayBZ.Internals.MArray
+ Data/ArrayBZ/ST.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE RankNTypes, TypeOperators #-}+{- |+   Module     : Data.ArrayBZ.ST+   Copyright  : (c) The University of Glasgow 2001 & (c) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: Hugs/GHC++Mutable boxed and unboxed arrays in the 'Control.Monad.ST.ST' monad.++-}++module Data.ArrayBZ.ST (++   -- * Boxed arrays+   STArray,             -- instance of: Eq, MArray+   runSTArray,++   -- * Unboxed arrays+   STUArray,            -- instance of: Eq, MArray+   runSTUArray,+   castSTUArray,        -- :: STUArray s i a -> ST s (STUArray s i b)++   -- * Overloaded mutable array interface+   module Data.ArrayBZ.MArray,+ ) where++import Control.Monad.ST ( ST, runST )++import Data.HasDefaultValue+import Data.Unboxed+import Data.ArrayBZ.MArray+import Data.ArrayBZ.Internals.Boxed+import Data.ArrayBZ.Internals.Unboxed++-- | A safe way to create and work with a mutable array before returning an+-- immutable array for later perusal.  This function avoids copying+-- the array before returning it - it uses 'unsafeFreeze' internally, but+-- this wrapper is a safe interface to that function.+runSTArray :: (Ix i)+           => (forall s . ST s (STArray s i e))+           -> Array i e+runSTArray st = runST (st >>= unsafeFreezeSTArray)++-- | A safe way to create and work with an unboxed mutable array before+-- returning an immutable array for later perusal.  This function+-- avoids copying the array before returning it - it uses+-- 'unsafeFreeze' internally, but this wrapper is a safe interface to+-- that function.+runSTUArray :: (Unboxed e, HasDefaultValue e, Ix i)+           => (forall s . ST s (STUArray s i e))+           -> UArray i e+runSTUArray st = runST (st >>= unsafeFreezeSTUArray)+
+ Data/ArrayBZ/Storable.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}+{- |+   Module     : Data.ArrayBZ.Storable+   Copyright  : (c) The University of Glasgow 2001 & (c) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: GHC/Hugs++A storable array is an IO-mutable array which stores its+contents in a contiguous memory block living in the C+heap. Elements are stored according to the class 'Storable'.+You can obtain the pointer to the array contents to manipulate+elements from languages like C.++It is similar to 'Data.ArrayBZ.IO.IOUArray' but slower.+Its advantage is that it's compatible with C.++-}++module Data.ArrayBZ.Storable (++    -- * Arrays of 'Storable' things.+    StorableArray, -- data StorableArray index element+                   --     -- index type must be in class Ix+                   --     -- element type must be in class Storable++    -- * Overloaded mutable array interface+    -- | Module "Data.ArrayBZ.Internals.MArray" provides the interface of storable arrays.+    -- They are instances of class 'MArray' (with the 'IO' monad).+    module Data.ArrayBZ.Internals.MArray,++    -- * Accessing the pointer to the array contents+    withStorableArray,  -- :: StorableArray i e -> (Ptr e -> IO a) -> IO a++    touchStorableArray, -- :: StorableArray i e -> IO ()++    -- * Casting ForeignPtr to StorableArray+    unsafeForeignPtrToStorableArray+    )+    where++import Data.Ix+import Foreign hiding (newArray)++import Data.ArrayBZ.Internals.IArray+import Data.ArrayBZ.Internals.MArray++-- ---------------------------------------------------------------------------++-- |The array type+data StorableArray i e = StorableArray !i !i !(ForeignPtr e)++instance HasBounds StorableArray where+    {-# INLINE bounds #-}+    bounds (StorableArray l u _) = (l,u)++instance HasMutableBounds StorableArray IO where+    {-# INLINE getBounds #-}+    getBounds (StorableArray l u _) = return (l,u)++instance Storable e => MArray StorableArray e IO where+    {-# INLINE newArray #-}+    newArray (l,u) init = do+        fp <- mallocForeignPtrArray size+        withForeignPtr fp $ \a ->+            sequence_ [pokeElemOff a i init | i <- [0..size-1]]+        return (StorableArray l u fp)+        where+        size = rangeSize (l,u)++    newArray_ (l,u) = do+        fp <- mallocForeignPtrArray (rangeSize (l,u))+        return (StorableArray l u fp)++    {-# INLINE unsafeRead #-}+    unsafeRead (StorableArray _ _ fp) i =+        withForeignPtr fp $ \a -> peekElemOff a i++    {-# INLINE unsafeWrite #-}+    unsafeWrite (StorableArray _ _ fp) i e =+        withForeignPtr fp $ \a -> pokeElemOff a i e+++{-# INLINE withStorableArray #-}+-- |The pointer to the array contents is obtained by 'withStorableArray'.+-- The idea is similar to 'ForeignPtr' (used internally here).+-- The pointer should be used only during execution of the 'IO' action+-- retured by the function passed as argument to 'withStorableArray'.+withStorableArray :: StorableArray i e -> (Ptr e -> IO a) -> IO a+withStorableArray (StorableArray _ _ fp) f = withForeignPtr fp f++-- |If you want to use it afterwards, ensure that you+-- 'touchStorableArray' after the last use of the pointer,+-- so the array is not freed too early.+touchStorableArray :: StorableArray i e -> IO ()+touchStorableArray (StorableArray _ _ fp) = touchForeignPtr fp++-- |Construct a 'StorableArray' from an arbitrary 'ForeignPtr'.  It is+-- the caller's responsibility to ensure that the 'ForeignPtr' points to+-- an area of memory sufficient for the specified bounds.+unsafeForeignPtrToStorableArray+   :: ForeignPtr e -> (i,i) -> IO (StorableArray i e)+unsafeForeignPtrToStorableArray p (l,u) =+   return (StorableArray l u p)
+ Data/ArrayBZ/Unboxed.hs view
@@ -0,0 +1,27 @@+{- |+   Module     : Data.ArrayBZ.Unboxed+   Copyright  : (c) The University of Glasgow 2001 & (c) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: Hugs/GHC++Unboxed arrays++-}++module Data.ArrayBZ.Unboxed (+           UArray,+           IOUArray,+           STUArray,+           castUArray,+           castIOUArray,+           castSTUArray,+           module Data.ArrayBZ.Internals.IArray,+           module Data.ArrayBZ.Internals.MArray,+  ) where++import Data.ArrayBZ.Internals.Unboxed+import Data.ArrayBZ.Internals.IArray+import Data.ArrayBZ.Internals.MArray
+ Data/HasDefaultValue.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE CPP #-}+{- |+   Module     : Data.HasDefaultValue+   Copyright  : Copyright (C) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: portable++Class 'HasDefaultValue' allows to declare type's default value++-}++module Data.HasDefaultValue (+           HasDefaultValue(..),+       )+where++import Data.Int+import Data.Word+import Foreign.Ptr+import Foreign.StablePtr++-- ---------------------------------------------------------------------------+-- | Types that has default value++class HasDefaultValue a where+    defaultValue :: a++instance HasDefaultValue Bool          where defaultValue = False+instance HasDefaultValue Char          where defaultValue = '\0'+instance HasDefaultValue Int           where defaultValue = 0+instance HasDefaultValue Int8          where defaultValue = 0+instance HasDefaultValue Int16         where defaultValue = 0+instance HasDefaultValue Int32         where defaultValue = 0+instance HasDefaultValue Int64         where defaultValue = 0+#if !defined(__HUGS__) || defined(__HUGS_VERSION__)+-- don't define this for Hugs2003+instance HasDefaultValue Word          where defaultValue = 0+#endif+instance HasDefaultValue Word8         where defaultValue = 0+instance HasDefaultValue Word16        where defaultValue = 0+instance HasDefaultValue Word32        where defaultValue = 0+instance HasDefaultValue Word64        where defaultValue = 0+instance HasDefaultValue Float         where defaultValue = 0+instance HasDefaultValue Double        where defaultValue = 0+instance HasDefaultValue (Ptr a)       where defaultValue = nullPtr+instance HasDefaultValue (FunPtr a)    where defaultValue = nullFunPtr+instance HasDefaultValue (StablePtr a) where defaultValue = castPtrToStablePtr nullPtr+
+ Data/Ref.hs view
@@ -0,0 +1,24 @@+{- |+   Module     : Data.Ref+   Copyright  : Copyright (C) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: Hugs/GHC++References (mutable vars)++-}++module Data.Ref (+    module Data.IORef,+    module Data.STRef,+    module Data.Ref.Unboxed,+    module Data.Ref.Universal,+  ) where++import Data.IORef+import Data.STRef+import Data.Ref.Unboxed+import Data.Ref.Universal
+ Data/Ref/LazyST.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE CPP #-}+{- |+   Module     : Data.Ref.LazyST+   Copyright  : Copyright (C) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: GHC/Hugs++Mutable boxed and unboxed references in the lazy ST monad.++-}++module Data.Ref.LazyST (+        -- * STRefs+        STRef,          -- abstract, instance Eq+        newSTRef,       -- :: a -> ST s (STRef s a)+        readSTRef,      -- :: STRef s a -> ST s a+        writeSTRef,     -- :: STRef s a -> a -> ST s ()+        modifySTRef,    -- :: STRef s a -> (a -> a) -> ST s ()++        -- * STURefs+        ST.STURef,      -- abstract, instance Eq+        newSTURef,      -- :: a -> ST s (STURef s a)+        readSTURef,     -- :: STURef s a -> ST s a+        writeSTURef,    -- :: STURef s a -> a -> ST s ()+        modifySTURef    -- :: STURef s a -> (a -> a) -> ST s ()+ ) where++import Control.Monad.ST.Lazy+import Data.STRef.Lazy+import qualified Data.Ref.Unboxed as ST+import Data.Unboxed++newSTURef    :: (Unboxed a) => a -> ST s (ST.STURef s a)+readSTURef   :: (Unboxed a) => ST.STURef s a -> ST s a+writeSTURef  :: (Unboxed a) => ST.STURef s a -> a -> ST s ()+modifySTURef :: (Unboxed a) => ST.STURef s a -> (a -> a) -> ST s ()++newSTURef   = strictToLazyST . ST.newSTURef+readSTURef  = strictToLazyST . ST.readSTURef+writeSTURef r a = strictToLazyST (ST.writeSTURef r a)+modifySTURef r f = strictToLazyST (ST.modifySTURef r f)+
+ Data/Ref/Unboxed.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE CPP #-}+{- |+   Module     : Data.Ref.Unboxed+   Copyright  : Copyright (C) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: GHC/Hugs++Unboxed references++Based on the idea of Oleg Kiselyov+  (see http://www.haskell.org/pipermail/haskell-cafe/2004-July/006400.html)+-}++module Data.Ref.Unboxed where++import Control.Monad.ST  (ST)+import Data.Typeable+#include "Typeable.h"++import Control.Monad.STorIO+import Data.Unboxed++-- -----------------------------------------------------------------------------+-- | Unboxed references in IO monad++newtype IOURef a = IOURef (IOSpecific2 MUVec a)++INSTANCE_TYPEABLE1(IOURef,ioURefTc,"IOURef")++-- | Create new unboxed reference in IO monad+newIOURef :: (Unboxed a) => a -> IO (IOURef a)+newIOURef init = do var <- allocUnboxed 1+                    writeUnboxed var 0 init+                    return (IOURef var)++-- | Read current value of unboxed reference in IO monad+{-# INLINE readIOURef #-}+readIOURef :: (Unboxed a) => IOURef a -> IO a+readIOURef (IOURef ref) = readUnboxed ref 0++-- | Change value of unboxed reference in IO monad+{-# INLINE writeIOURef #-}+writeIOURef :: (Unboxed a) => IOURef a -> a -> IO ()+writeIOURef (IOURef ref) = writeUnboxed ref 0++-- |Modify contents of an 'IOURef' by applying pure function to it+{-# INLINE modifyIOURef #-}+modifyIOURef :: (Unboxed a) => IOURef a -> (a -> a) -> IO ()+modifyIOURef ref f  =  readIOURef ref >>= writeIOURef ref . f++-- -----------------------------------------------------------------------------+-- | Unboxed references in ST monad++newtype STURef s a = STURef (MUVec s a)++INSTANCE_TYPEABLE2(STURef,stURefTc,"STURef")++-- | Create new unboxed reference in ST monad+newSTURef :: (Unboxed a) => a -> ST s (STURef s a)+newSTURef init = do var <- allocUnboxed 1+                    writeUnboxed var 0 init+                    return (STURef var)++-- | Read current value of unboxed reference in ST monad+{-# INLINE readSTURef #-}+readSTURef :: (Unboxed a) => STURef s a -> ST s a+readSTURef (STURef ref) = readUnboxed ref 0++-- | Change value of unboxed reference in ST monad+{-# INLINE writeSTURef #-}+writeSTURef :: (Unboxed a) => STURef s a -> a -> ST s ()+writeSTURef (STURef ref) = writeUnboxed ref 0++-- |Modify contents of an 'STURef' by applying pure function to it+{-# INLINE modifySTURef #-}+modifySTURef :: (Unboxed a) => STURef s a -> (a -> a) -> ST s ()+modifySTURef ref f  =  readSTURef ref >>= writeSTURef ref . f+
+ Data/Ref/Universal.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE CPP, FunctionalDependencies, MultiParamTypeClasses #-}+{- |+   Module     : Data.Ref.Universal+   Copyright  : Copyright (C) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: Hugs/GHC++Monad-independent interfaces for boxed and unboxed references++-}++module Data.Ref.Universal (+           -- * Monad-independent interface for boxed references+           Ref(..),+           modifyRef,+           modifyRefM,+           -- * Monad-independent interface for unboxed references+           URef(..),+           modifyURef,+           modifyURefM,+       )+where++import Control.Monad.ST (ST)+import Data.IORef+import Data.STRef++import Data.Unboxed+import Data.Ref.Unboxed++-- -----------------------------------------------------------------------------+-- | This class allows to create new boxed reference in monad-independent way+--     (suitable for writing code that will work in IO, ST and other monads)++class (Monad m) => Ref m r | m->r, r->m where+    -- |Create a new 'Ref' with given initial value+    newRef :: a -> m (r a)+    -- |Read the value of an 'Ref'+    readRef   :: r a -> m a+    -- |Write new value into an 'Ref'+    writeRef  :: r a -> a -> m ()++instance Ref IO IORef where+    newRef = newIORef+    readRef = readIORef+    writeRef = writeIORef+instance Ref (ST s) (STRef s) where+    newRef = newSTRef+    readRef = readSTRef+    writeRef = writeSTRef++-- |Modify the contents of an 'Ref' by applying pure function to it+{-# INLINE modifyRef #-}+modifyRef  ref f  =  readRef ref >>= writeRef ref . f++-- |Modify the contents of an 'Ref' by applying monadic computation to it+{-# INLINE modifyRefM #-}+modifyRefM ref f  =  readRef ref >>= f >>= writeRef ref++-- -----------------------------------------------------------------------------+-- | This class allows to create new unboxed reference in monad-independent way+--     (suitable for writing code that will work in IO, ST and other monads)++class (Monad m) => URef m r | m->r, r->m where+    -- |Create a new 'URef' with given initial value+    newURef    :: (Unboxed a) => a -> m (r a)+    -- |Read the value of an 'URef'+    readURef   :: (Unboxed a) => r a -> m a+    -- |Write new value into an 'URef'+    writeURef  :: (Unboxed a) => r a -> a -> m ()++instance URef IO IOURef where+    newURef = newIOURef+    readURef = readIOURef+    writeURef = writeIOURef+instance URef (ST s) (STURef s) where+    newURef = newSTURef+    readURef = readSTURef+    writeURef = writeSTURef++-- |Modify the contents of an 'URef' by applying pure function to it+{-# INLINE modifyURef #-}+modifyURef  ref f  =  readURef ref >>= writeURef ref . f++-- |Modify the contents of an 'URef' by applying monadic computation to it+{-# INLINE modifyURefM #-}+modifyURefM ref f  =  readURef ref >>= f >>= writeURef ref+
+ Data/SyntaxSugar.hs view
@@ -0,0 +1,131 @@+{-# LANGUAGE CPP, FunctionalDependencies, FlexibleInstances, MultiParamTypeClasses #-}+{- |+   Module     : Data.SyntaxSugar+   Copyright  : Copyright (C) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: Hugs/GHC++Universal interface for reading and writing mutable data+  (references, array and hash elements)+Syntax sugar (=:, +=, val...) based on this interface++-}++module Data.SyntaxSugar where++import Control.Monad.ST (ST)+import Data.ArrayBZ.IO+import Data.ArrayBZ.ST+import Data.ArrayBZ.Storable+import Data.HashTable as Hash+import Data.Ref+import Data.Unboxed+import Foreign.Storable++-- -----------------------------------------------------------------------------+-- Universal interface for reading and writing mutable data+--   (references, array and hash elements)++class (Monad m) => Mutable m r a | r->a where+    -- |Read the value of an 'Mutable'+    readVar  :: r -> m a+    -- |Write new value into an 'Mutable'+    writeVar :: r -> a -> m ()++-- |Modify the contents of an 'Mutable' by applying pure function to it+{-# INLINE modifyVar #-}+modifyVar  var f  =  readVar var >>= writeVar var . f++-- |Modify the contents of an 'Mutable' by applying monadic computation to it+{-# INLINE modifyVarM #-}+modifyVarM var f  =  readVar var >>= f >>= writeVar var++-- -----------------------------------------------------------------------------+-- Implementation of `Mutable` interface for references++instance Mutable IO (IORef a) a where+    readVar  = readRef+    writeVar = writeRef+instance Mutable (ST s) (STRef s a) a where+    readVar  = readRef+    writeVar = writeRef+instance (Unboxed a) => Mutable IO (IOURef a) a where+    readVar  = readURef+    writeVar = writeURef+    {-# INLINE readVar  #-}+    {-# INLINE writeVar #-}+instance (Unboxed a) => Mutable (ST s) (STURef s a) a where+    readVar  = readURef+    writeVar = writeURef++-- -----------------------------------------------------------------------------+-- Implementation of `Mutable` interface for elements of MArray,+--   including simplified interfaces for 2-dimensional and 3-dimensional arrays++instance (Ix i) => Mutable IO (IOArray i e, i) e where+    readVar  (arr,i) = readArray  arr i+    writeVar (arr,i) = writeArray arr i++instance (Unboxed e, Ix i) => Mutable IO (IOUArray i e, i) e where+    readVar  (arr,i) = readArray  arr i+    writeVar (arr,i) = writeArray arr i++instance (Storable e, Ix i) => Mutable IO (StorableArray i e, i) e where+    readVar  (arr,i) = readArray  arr i+    writeVar (arr,i) = writeArray arr i++instance (Ix i) => Mutable (ST s) (STArray s i e, i) e where+    readVar  (arr,i) = readArray  arr i+    writeVar (arr,i) = writeArray arr i++instance (Unboxed e, Ix i) => Mutable (ST s) (STUArray s i e, i) e where+    readVar  (arr,i) = readArray  arr i+    writeVar (arr,i) = writeArray arr i++instance (MArray a e m, Ix i, Ix j) => Mutable m (a (i,j) e, i, j) e where+    readVar  (arr,i,j) = readArray  arr (i,j)+    writeVar (arr,i,j) = writeArray arr (i,j)++instance (MArray a e m, Ix i, Ix j, Ix k) => Mutable m (a (i,j,k) e, i, j, k) e where+    readVar  (arr,i,j,k) = readArray  arr (i,j,k)+    writeVar (arr,i,j,k) = writeArray arr (i,j,k)++-- -----------------------------------------------------------------------------+-- Implementation of `Mutable` interface for values in HashTable++instance Mutable IO (HashTable key e, key) e where+    readVar  (table,key)   = do (Just x) <- Hash.lookup table key+                                return x+    writeVar (table,key) e = hashUpdate table key e >> return ()++#if defined(__HUGS_VERSION__)  ||  defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 604)+-- Define this only for Hugs2005+ and GHC 6.4++hashUpdate table = Hash.update table+#else+-- Slower implementation for old compilers+hashUpdate table key e = do Hash.delete table key+                            Hash.insert table key e+#endif+++-- -----------------------------------------------------------------------------+-- Syntax sugar for using mutables++infixl 0 =:, +=, -=, .=, .<-+ref  x  = newRef  x                           -- create new boxed reference+uref x  = newURef x                           -- create new unboxed reference+val var = readVar    var                      -- read current value of mutable+var=:x  = writeVar   var x                    -- assign new value to mutable+var+=x  = modifyVar  var (\old -> old+x)      -- increase value of mutable+var-=x  = modifyVar  var (\old -> old-x)      -- decrease value of mutable+var.=f  = modifyVar  var (\old -> f old)      -- apply pure function to the value of mutable+var.<-f = modifyVarM var (\old -> f old)      -- apply monadic computation to the value of mutable++{-# INLINE ref  #-}+{-# INLINE uref #-}+{-# INLINE (=:) #-}+{-# INLINE (+=) #-}+{-# INLINE (-=) #-}
+ Data/Unboxed.hs view
@@ -0,0 +1,151 @@+{-# LANGUAGE CPP, ScopedTypeVariables #-}+{- |+   Module     : Data.Unboxed+   Copyright  : Copyright (C) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: Hugs/GHC++Class 'Unboxed' represents values that can be stored in unboxed vectors+  and unboxed references++Based on the: Hugs.ByteArray module+-}++module Data.Unboxed (+           UVec,+           MUVec,+           allocUnboxed,+           unsafeFreezeUnboxed,+           unsafeThawUnboxed,+           freezeUnboxed,+           thawUnboxed,+           castUnboxed,+           castMUnboxed,++           Unboxed,+           readUnboxed,+           writeUnboxed,+           indexUnboxed,+           sizeOfUnboxed,+       )+where++-- On GHC we use fast compiler-specific implementation.+-- On other compilers, slow but universal Storable-based implementation is used+#ifdef __GLASGOW_HASKELL__++import GHC.Unboxed++#else++import Control.Monad.STorIO+import Data.Int+import Data.Word+import Foreign.ForeignPtr+import Foreign.Marshal.Utils    ( copyBytes )+import Foreign.Ptr+import Foreign.StablePtr+import Foreign.Storable+import System.IO.Unsafe++-- ---------------------------------------------------------------------------+-- | Immutable and mutable byte vectors++newtype  UVec   a =  UVec (ForeignPtr a)+newtype MUVec s a = MUVec (ForeignPtr a)++-- | Alloc the mutable byte vector+allocUnboxedBytes :: (STorIO m s, Integral bytes, Unboxed a)+                  => bytes -> m (MUVec s a)+allocUnboxedBytes bytes = do+    fp <- mLift (mallocForeignPtrBytes (fromIntegral bytes))+    return (MUVec fp)++-- | Mutable->immutable byte vector on-place conversion+{-# INLINE unsafeFreezeMUVec #-}+unsafeFreezeUnboxed :: (STorIO m s)+                => MUVec s a -> m (UVec a)+unsafeFreezeUnboxed (MUVec arr) = do+    return (UVec arr)++-- | Immutable->mutable byte vector on-place conversion+{-# INLINE unsafeThawUVec #-}+unsafeThawUnboxed :: (STorIO m s)+             => UVec a -> m (MUVec s a)+unsafeThawUnboxed (UVec arr) = do+    return (MUVec arr)++-- | Mutable->immutable byte vector conversion which takes a copy of contents+freezeUnboxed :: (STorIO m s)+                => MUVec s a -> Int -> m (UVec a)+freezeUnboxed (MUVec arr) size = mLift $ do+    arr' <- mallocForeignPtrBytes size+    withForeignPtr arr $ \p ->+        withForeignPtr arr' $ \p' ->+            copyBytes p' p size+    return (UVec arr')++-- | Immutable->mutable byte vector conversion which takes a copy of contents+thawUnboxed :: (STorIO m s) => UVec a -> Int -> m (MUVec s a)+thawUnboxed (UVec arr) size = mLift $ do+    arr' <- mallocForeignPtrBytes size+    withForeignPtr arr $ \p ->+        withForeignPtr arr' $ \p' ->+            copyBytes p' p size+    return (MUVec arr')++-- ---------------------------------------------------------------------------+-- | Unboxed defined via Storable++class    (Storable value) => Unboxed value+instance (Storable value) => Unboxed value++-- | Read the value from mutable byte vector at given `index`+{-# INLINE readUnboxed #-}+readUnboxed :: (STorIO m s, Unboxed value, Integral index)+            => MUVec s value -> index -> m value+readUnboxed (MUVec arr) index = mLift $+    withForeignPtr arr $ \a -> peekElemOff a (fromIntegral index)++-- | Write the value to mutable byte vector at given `index`+{-# INLINE writeUnboxed #-}+writeUnboxed :: (STorIO m s, Unboxed value, Integral index)+             => MUVec s value -> index -> value -> m ()+writeUnboxed (MUVec arr) index value = mLift $+    withForeignPtr arr $ \a -> pokeElemOff a (fromIntegral index) value++-- | Read the value from immutable byte vector at given `index`+{-# INLINE indexUnboxed #-}+indexUnboxed :: (Unboxed value, Integral index)+             => UVec value -> index -> value+indexUnboxed (UVec arr) index = unsafePerformIO $+    withForeignPtr arr $ \a -> peekElemOff a (fromIntegral index)++-- | How many bytes required to represent values of this type+{-# INLINE sizeOfUnboxed #-}+sizeOfUnboxed :: (Unboxed value, Integral size)+              => value -> size+sizeOfUnboxed = fromIntegral . sizeOf++-- | Recast immutable unboxed vector+castUnboxed :: UVec a    -> UVec b+castUnboxed   (UVec vec) =  UVec (castForeignPtr vec)++-- | Recast mutable unboxed vector+castMUnboxed :: MUVec s a   -> MUVec s b+castMUnboxed   (MUVec mvec) =  MUVec (castForeignPtr mvec)++#endif++-- ---------------------------------------------------------------------------+-- | Additional operations on byte vectors++-- | Alloc the mutable byte vector having `elems` elements of required type+allocUnboxed :: forall s a elems m. (STorIO m s, Integral elems, Unboxed a)+             => elems -> m (MUVec s a)+allocUnboxed elems =+    allocUnboxedBytes (fromIntegral elems * sizeOfUnboxed (undefined::a))+
+ Examples/Array/Boxed.hs view
@@ -0,0 +1,36 @@+-- This example demonstrates using of Array, IOArray and STArray+import Control.Monad.ST+import Data.ArrayBZ.Boxed++main = do+          -- This section demonstrates using of Array+          test_Array          |>  print++          -- This section demonstrates using of IOArray+          test_IOArray        >>= print++          -- This section demonstrates using of STArray+          runST test_STArray  |>  print+++-- Using Array+test_Array =+          let array = listArray (1,10) [1..10] :: Array Int Double+              elements = elems array+          in (sum elements)++-- Using IOArray+test_IOArray = do+          array <- newListArray (1,10) [1..10] :: IO (IOArray Int Double)+          elements <- getElems array+          return (sum elements)++-- Using STArray+test_STArray = do+          array <- newListArray (1,10) [1..10] :: ST s (STArray s Int Double)+          elements <- getElems array+          return (sum elements)++-- Helper operation+a |> b = b a+
+ Examples/Array/Diff.hs view
@@ -0,0 +1,25 @@+-- This example demonstrates using of DiffArray and DiffUArray+import Data.ArrayBZ.Diff++main = do+          -- This section demonstrates using of DiffArray+          test_DiffArray          |>  print++          -- This section demonstrates using of DiffUArray+          test_DiffUArray         |>  print++-- Using DiffArray+test_DiffArray =+          let array = listArray (1,10) [1..10] :: DiffArray Int Double+              elements = elems array+          in (sum elements)++-- Using DiffUArray+test_DiffUArray =+          let array = listArray (1,10) [1..10] :: DiffUArray Int Double+              elements = elems array+          in (sum elements)++-- Helper operation+a |> b = b a+
+ Examples/Array/Dynamic.hs view
@@ -0,0 +1,45 @@+-- This example demonstrates using of `DynamicIOArray`,+-- i.e. arrays whose bounds can be changed dynamically,+-- including automatic growth as `writeArray` requires.+--+-- Other types of dynamic arrays - DynamicIOUArray, DynamicSTArray,+-- DynamicSTUArray and manually constructed dynamic array types+-- can be used in the same fashion.+import Data.ArrayBZ.Dynamic++main = do+          -- This array will grow at least two times each time when index is out of bounds,+          -- because it is created using `newDynamicArray growTwoTimes`+          arr <- newDynamicArray growTwoTimes (0,-1) 99 :: IO (DynamicIOArray Int Int)+          -- At this moment the array is empty+          printArray arr++          -- During this cycle the array extended 3 times+          for [0..5] $ \i ->+             writeArray arr i i+          printArray arr++          -- During this cycle the array extended one more time+          for [-5 .. -1] $ \i ->+             writeArray arr i i+          printArray arr++          -- Operation that explicitly resizes the array+          resizeDynamicArray arr (3,15)+          printArray arr++          -- This array will not grow automatically because it is created using `newArray`,+          -- but it can be resized explicitly using `resizeDynamicArray`+          arr <- newArray (0,-1) 99 :: IO (DynamicIOArray Int Int)+          resizeDynamicArray arr (0,0)+          printArray arr+          writeArray arr 1 1  -- this operation raises error+++-- Print dynamic array bounds and contents+printArray arr = do+          bounds   <- getBounds arr+          contents <- getElems  arr+          putStrLn (show bounds++" : "++show contents)++for list action = mapM_ action list
+ Examples/Array/IO.hs view
@@ -0,0 +1,26 @@+-- This example demonstrates using of IOArray and IOUArray+import Data.ArrayBZ.IO++main = do+          -- This section demonstrates using of IOArray+          test_IOArray        >>= print++          -- This section demonstrates using of IOUArray+          test_IOUArray       >>= print+++-- Using IOArray+test_IOArray = do+          array <- newListArray (1,10) [1..10] :: IO (IOArray Int Double)+          elements <- getElems array+          return (sum elements)++-- Using IOUArray+test_IOUArray = do+          array <- newListArray (1,10) [1..10] :: IO (IOUArray Int Double)+          elements <- getElems array+          return (sum elements)++-- Helper operation+a |> b = b a+
+ Examples/Array/ST.hs view
@@ -0,0 +1,27 @@+-- This example demonstrates using of STArray and STUArray+import Control.Monad.ST+import Data.ArrayBZ.ST++main = do+          -- This section demonstrates using of STArray+          runST test_STArray  |>  print++          -- This section demonstrates using of STUArray+          runST test_STUArray  |>  print+++-- Using STArray+test_STArray = do+          array <- newListArray (1,10) [1..10] :: ST s (STArray s Int Double)+          elements <- getElems array+          return (sum elements)++-- Using STUArray+test_STUArray = do+          array <- newListArray (1,10) [1..10] :: ST s (STUArray s Int Double)+          elements <- getElems array+          return (sum elements)++-- Helper operation+a |> b = b a+
+ Examples/Array/Storable.hs view
@@ -0,0 +1,14 @@+-- This example demonstrates using of StorableArray+import Data.ArrayBZ.Storable++main = do+          -- This section demonstrates using of StorableArray+          test_StorableArray        >>= print+++-- Using StorableArray+test_StorableArray = do+          array <- newListArray (1,10) [1..10] :: IO (StorableArray Int Double)+          elements <- getElems array+          return (sum elements)+
+ Examples/Array/Unboxed.hs view
@@ -0,0 +1,36 @@+-- This example demonstrates using of UArray, IOUArray and STUArray+import Control.Monad.ST+import Data.ArrayBZ.Unboxed++main = do+          -- This section demonstrates using of UArray+          test_UArray          |>  print++          -- This section demonstrates using of IOUArray+          test_IOUArray        >>= print++          -- This section demonstrates using of STUArray+          runST test_STUArray  |>  print+++-- Using UArray+test_UArray =+          let array = listArray (1,10) [1..10] :: UArray Int Double+              elements = elems array+          in (sum elements)++-- Using IOUArray+test_IOUArray = do+          array <- newListArray (1,10) [1..10] :: IO (IOUArray Int Double)+          elements <- getElems array+          return (sum elements)++-- Using STUArray+test_STUArray = do+          array <- newListArray (1,10) [1..10] :: ST s (STUArray s Int Double)+          elements <- getElems array+          return (sum elements)++-- Helper operation+a |> b = b a+
+ Examples/SyntaxSugar.hs view
@@ -0,0 +1,81 @@+-- This module demonstrates using of syntax sugar when manipulating+--   references, arrays and hash tables, including implementation+--   of monad-independent algorithms with references+import Control.Monad.ST+import Data.SyntaxSugar+import Data.Ref+import Data.ArrayBZ.IO+import Data.HashTable as Hash++main = do+          -- This section demonstrates running of monad-independent+          -- algorithm that use boxed references in IO and ST monads+          test_Ref 5            >>= print+          runST (test_Ref 6)    |>  print++          -- This section demonstrates running of monad-independent+          -- algorithm that use unboxed references in IO and ST monads+          test_URef 7           >>= print+          runST (test_URef 8)   |>  print++          -- Using syntax sugar with arrays+          test_Array            >>= print++          -- Using syntax sugar with hash tables+          test_Hash             >>= print+++-- Monad-independent computation that uses boxed reference+test_Ref init = do+          x <- ref (0::Int)+          x =: init+          x += 10+          x -= 2+          x .= (*2)+          val x++-- Monad-independent computation that uses unboxed reference+test_URef init = do+          x <- uref (0::Int)+          x =: init+          x += 10+          x -= 2+          x .= (*2)+          val x++-- Using syntax sugar with arrays+test_Array = do+          let i = 0::Int++          arr <- newArray (0,9) 0 :: IO (IOArray Int Double)+          (arr,i) =: 1+          (arr,i) += 10+          (arr,i) -= 2+          (arr,i) .= (*2)+          x <- val (arr,i)++          arr2 <- newArray ((0,0), (9,9)) 0 :: IO (IOArray (Int,Int) Double)+          (arr2,i,i) =: 1+          (arr2,i,i) += 10+          (arr2,i,i) -= 2+          (arr2,i,i) .= (*2)+          y <- val (arr2,i,i)++          return (x,y)+++-- Using syntax sugar with hash tables+test_Hash = do+          let key = "test"+          hash <- Hash.new (==) hashString+          (hash,key) =: 1+          (hash,key) += 10+          (hash,key) -= 2+          (hash,key) .= (*2)+          val (hash,key)+++-- Helper operations+a |> b = b a+for list action = mapM_ action list+
+ Examples/URef.hs view
@@ -0,0 +1,29 @@+-- This program demonstrates using of fast unboxed references in IO and ST monads+import Control.Monad.ST+import Data.Ref+import Data.Ref.LazyST ()++main = do+          -- IOURef is fast unboxed reference in IO monad+          test_IOURef 1         >>= print++          -- STURef is fast unboxed reference in ST monad+          runST (test_STURef 2) |>  print+++-- Using 'IOURef Int'+test_IOURef init = do+          x <- newIOURef (init::Int)+          x0 <- readIOURef x+          writeIOURef x (x0+10)+          readIOURef x++-- Using 'STURef Int'+test_STURef init = do+          x <- newSTURef (init::Int)+          x0 <- readSTURef x+          writeSTURef x (x0+10)+          readSTURef x++-- Helper operation+a |> b = b a
+ Examples/Universal.hs view
@@ -0,0 +1,37 @@+-- This program demonstrates implementation of monad-independent algorithms+-- using Ref and URef classes+import Control.Monad.ST+import Data.Ref++main = do+          -- This section demonstrates running of monad-independent algrorithm+          -- `test_Ref` in IO and ST monads+          test_Ref 3         >>= print+          runST (test_Ref 4) |>  print++          -- This section demonstrates running of monad-independent algrorithm+          -- `test_URef` in IO and ST monads+          test_URef 5         >>= print+          runST (test_URef 6) |>  print+++-- Using class 'Ref'+test_Ref init = do+          x <- newRef (init::Int)   -- `newRef` operation will create+                                    --    * IORef in IO monad+                                    --    * STRef in ST monad+          x0 <- readRef x           -- `readRef` and `writeRef` operations+          writeRef x (x0+10)        --   works with references of both types+          readRef x++-- Using class 'URef'+test_URef init = do+          x <- newURef (init::Int)  -- `newURef` operation will create+                                    --    * IOURef in IO monad+                                    --    * STURef in ST monad+          x0 <- readURef x          -- `readURef` and `writeURef` operations+          writeURef x (x0+10)       --   works with references of both types+          readURef x++-- Helper operation+a |> b = b a
+ GHC/ArrBZ.hs view
@@ -0,0 +1,105 @@+{-# LANGUAGE UnboxedTuples, MagicHash #-}+{- |+   Module     : GHC.ArrBZ+   Copyright  : Copyright (C) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: GHC++Vectors of boxed values++-}++module GHC.ArrBZ where++import GHC.Base++import Control.Monad.STorIO++-- ---------------------------------------------------------------------------+-- | Immutable and mutable vectors of boxed values++data  Vec   a  =   Vec (Array# a)+data MVec s a  =  MVec (MutableArray# s a)++-- | Alloc the mutable vector+allocBoxed :: (STorIO m s, Integral elems) => elems -> a -> m (MVec s a)+-- | Mutable->immutable vector on-place conversion+unsafeFreezeBoxed :: (STorIO m s) => MVec s a -> m (Vec a)+-- | Immutable->mutable vector on-place conversion+unsafeThawBoxed :: (STorIO m s) => Vec a -> m (MVec s a)+-- | Mutable->immutable vector conversion which takes a copy of contents+freezeBoxed :: (STorIO m s) => MVec s a -> Int -> a -> m (Vec a)+-- | Immutable->mutable vector conversion which takes a copy of contents+thawBoxed :: (STorIO m s) => Vec a -> Int -> a -> m (MVec s a)+++allocBoxed elems init = mLift ( \s ->+  case newArray# (fromI# elems) init s of { (# s, arr #) ->+  (# s, MVec arr #) } )++{-# INLINE unsafeFreezeBoxed #-}+unsafeFreezeBoxed (MVec mvec) = mLift ( \s ->+  case unsafeFreezeArray# mvec s of { (# s, vec #) ->+  (# s, Vec vec #) } )++{-# INLINE unsafeThawBoxed #-}+unsafeThawBoxed (Vec arr#) = mLift ( \s ->+  case unsafeThawArray# arr# s of { (# s, marr# #) ->+  (# s, MVec marr# #) } )++freezeBoxed (MVec marr#) (I# n#) init = mLift ( \s1# ->+    case newArray# n# init                s1#  of { (# s2#, tmparr# #) ->++    let copy i# s01# | i# ==# n# =        s01#+                     | otherwise =+            case readArray#  marr#   i#   s01# of { (# s02#, e #) ->+            case writeArray# tmparr# i# e s02# of { s03# ->+            copy (i# +# 1#)               s03# }} in++    case copy 0#                          s2#  of { s3# ->+    case unsafeFreezeArray# tmparr#       s3#  of { (# s4#, arr# #) ->+    (# s4#, Vec arr# #) }}} )++thawBoxed (Vec vec#) (I# n#) init = mLift ( \s1# ->+    case newArray# n# init s1#               of { (# s2#, mvec# #) ->++    let copy i# s01# | i# ==# n# =      s01#+                     | otherwise =+            case indexArray# vec#  i#        of { (# e #) ->+            case writeArray# mvec# i# e s01# of { s02# ->+            copy (i# +# 1#)             s02# }} in++    case copy 0#                        s2#  of { s3# ->+    (# s3#, MVec mvec# #) }} )++-- Implementation helper function that converts any integral value to the Int#+{-# INLINE fromI# #-}+fromI# :: (Integral n) => n -> Int#+fromI# n = n#   where I# n# = fromIntegral n++-- ---------------------------------------------------------------------------+-- Read/write/index vector elements++-- | Read the value from mutable vector at given `index`+readBoxed    :: (STorIO m s, Integral index) => MVec s value -> index -> m value+-- | Write the value to mutable vector at given `index`+writeBoxed   :: (STorIO m s, Integral index) => MVec s value -> index -> value -> m ()+-- | Read the value from immutable vector at given `index`+indexBoxed   :: (Integral index) => Vec value -> index -> value+++{-# INLINE readBoxed #-}+readBoxed (MVec vec) index  =  mLift (readArray# vec (fromI# index))++{-# INLINE writeBoxed #-}+writeBoxed (MVec vec) index value  =  mLift ( \s ->+    case writeArray# vec (fromI# index) value s of { s ->+    (# s, () #) } )++{-# INLINE indexBoxed #-}+indexBoxed (Vec vec) index  =+    case indexArray# vec (fromI# index) of { (# s #) -> s }+
+ GHC/Unboxed.hs view
@@ -0,0 +1,185 @@+{-# LANGUAGE FunctionalDependencies, FlexibleInstances, UnliftedFFITypes,+  CPP, KindSignatures, MagicHash, UnboxedTuples, ForeignFunctionInterface,+  MultiParamTypeClasses #-}+{- |+   Module     : GHC.Unboxed+   Copyright  : Copyright (C) 2006 Bulat Ziganshin+   License    : BSD3++   Maintainer : Bulat Ziganshin <Bulat.Ziganshin@gmail.com>+   Stability  : experimental+   Portability: GHC++Unboxed values (simple datatypes that can be stored in ByteArrays,+  i.e. raw memory buffers allocated inside the Haskell heap)++Based on the idea of Oleg Kiselyov+  (see http://www.haskell.org/pipermail/haskell-cafe/2004-July/006400.html)+-}++module GHC.Unboxed where++import GHC.ST           ( ST(..), runST )+import GHC.IOBase       ( IO(..) )+import GHC.Base+import GHC.Word         ( Word(..) )+import GHC.Ptr          ( Ptr(..), FunPtr(..) )+import GHC.Float        ( Float(..), Double(..) )+import GHC.Stable       ( StablePtr(..) )+import GHC.Int          ( Int8(..),  Int16(..),  Int32(..),  Int64(..) )+import GHC.Word         ( Word8(..), Word16(..), Word32(..), Word64(..) )+import Control.Monad.ST.Lazy    ( strictToLazyST )+import qualified Control.Monad.ST.Lazy as Lazy (ST)+import Foreign.Storable++-- ---------------------------------------------------------------------------+-- | That's all we need to unify ST and IO operations!+class (Monad m) => STorIO m s | m->s where+    mLift :: (State# s -> (# State# s, a #)) -> m a++instance STorIO (ST s) s where+    {-# INLINE mLift #-}+    mLift = ST++instance STorIO (Lazy.ST s) s where+    {-# INLINE mLift #-}+    mLift = strictToLazyST . ST++instance STorIO IO RealWorld where+    {-# INLINE mLift #-}+    mLift = IO++-- | Type functions which converts universal ST or IO types to IO-specific ones+type IOSpecific  (a :: * -> *)           = a RealWorld+type IOSpecific2 (a :: * -> * -> *)       = a RealWorld+type IOSpecific3 (a :: * -> * -> * -> *)   = a RealWorld++-- ---------------------------------------------------------------------------+-- | Immutable and mutable byte vectors++data  UVec   a  =   UVec ByteArray#+data MUVec s a  =  MUVec (MutableByteArray# s)++-- | Alloc the mutable byte vector+allocUnboxedBytes :: (STorIO m s, Integral bytes, Unboxed a)+                  => bytes -> m (MUVec s a)+allocUnboxedBytes bytes = mLift ( \s ->+    case newByteArray# (fromI# bytes) s of { (# s, arr #) ->+    (# s, MUVec arr #) } )++-- | Mutable->immutable byte vector on-place conversion+{-# INLINE unsafeFreezeUnboxed #-}+unsafeFreezeUnboxed :: (STorIO m s) => MUVec s a -> m (UVec a)+unsafeFreezeUnboxed (MUVec marr#) = mLift ( \s ->+    case unsafeFreezeByteArray# marr# s of { (# s, arr# #) ->+    (# s, UVec arr# #) } )++-- | Immutable->mutable byte vector on-place conversion+{-# INLINE unsafeThawUnboxed #-}+unsafeThawUnboxed :: (STorIO m s) => UVec a -> m (MUVec s a)+unsafeThawUnboxed (UVec arr#) = mLift ( \s ->+    (# s, MUVec (unsafeCoerce# arr#) #) )++-- | Mutable->immutable byte vector conversion which takes a copy of contents+freezeUnboxed :: (STorIO m s) => MUVec s a -> Int -> m (UVec a)+freezeUnboxed (MUVec marr#) (I# size) = mLift ( \s1# ->+    case newByteArray# size                      s1# of { (# s2#, tmparr# #) ->+    case unsafeCoerce# memcpy tmparr# marr# size s2# of { (# s3#, () #) ->+    case unsafeFreezeByteArray# tmparr#          s3# of { (# s4#, arr# #) ->+    (# s3#, UVec arr# #) }}} )++-- | Immutable->mutable byte vector conversion which takes a copy of contents+thawUnboxed :: (STorIO m s) => UVec a -> Int -> m (MUVec s a)+thawUnboxed (UVec arr#) (I# size) = mLift (  \s1# ->+    case newByteArray# size                   s1# of { (# s2#, marr# #) ->+    case unsafeCoerce# memcpy marr# arr# size s2# of { (# s3#, () #) ->+    (# s3#, MUVec marr# #) }} )++-- | Recast immutable unboxed vector+castUnboxed :: UVec a    -> UVec b+castUnboxed   (UVec vec) =  UVec vec++-- | Recast mutable unboxed vector+castMUnboxed :: MUVec s a   -> MUVec s b+castMUnboxed   (MUVec mvec) =  MUVec mvec++-- Implementation helper function that converts any integral value to the Int#+{-# INLINE fromI# #-}+fromI# :: (Integral n) => n -> Int#+fromI# n = n#   where I# n# = fromIntegral n++-- Implementation helper function that copies data between byte vectors+foreign import ccall unsafe "memcpy"+    memcpy :: MutableByteArray# RealWorld -> ByteArray# -> Int# -> IO ()++-- ---------------------------------------------------------------------------+-- | Unboxed is like Storable, but values are stored in byte vectors (i.e. inside the Haskell heap)++class Unboxed value where+    -- | Read the value from mutable byte vector at given `index`+    readUnboxed    :: (STorIO m s, Integral index) => MUVec s value -> index -> m value+    -- | Write the value to mutable byte vector at given `index`+    writeUnboxed   :: (STorIO m s, Integral index) => MUVec s value -> index -> value -> m ()+    -- | Read the value from immutable byte vector at given `index`+    indexUnboxed   :: (Integral index) => UVec value -> index -> value+    -- | How many bytes required to represent values of this type+    sizeOfUnboxed  :: value -> Int++-- Universal defition for Enum types having <= 256 variants+instance Unboxed Bool where+{+    {-# INLINE readUnboxed #-};+    readUnboxed (MUVec arr) index  =  mLift ( \s ->+        case readInt8Array# arr (fromI# index) s of { (# s, value# #) ->+        (# s, tagToEnum# value# #) } );++    {-# INLINE writeUnboxed #-};+    writeUnboxed (MUVec arr) index value  =  mLift ( \s ->+        case writeInt8Array# arr (fromI# index) (getTag value) s of { s ->+        (# s, () #) } );++    {-# INLINE indexUnboxed #-};+    indexUnboxed (UVec arr) index  =  tagToEnum# (indexInt8Array# arr (fromI# index));++    {-# INLINE sizeOfUnboxed #-};+    sizeOfUnboxed _ = 1;+}++-- Universal defition for Storable types+#define InstanceUnboxed(type, cast, read, write, at)                  \+instance Unboxed type where                                           \+{                                                                     \+    {-# INLINE readUnboxed #-};                                       \+    readUnboxed (MUVec arr) index  =  mLift ( \s ->                   \+        case read arr (fromI# index) s of { (# s, value# #) ->        \+        (# s, cast value# #) } );                                     \+                                                                      \+    {-# INLINE writeUnboxed #-};                                      \+    writeUnboxed (MUVec arr) index (cast value#)  =  mLift ( \s ->    \+        case write arr (fromI# index) value# s of { s ->              \+        (# s, () #) } );                                              \+                                                                      \+    {-# INLINE indexUnboxed #-};                                      \+    indexUnboxed (UVec arr) index  =  cast (at arr (fromI# index));   \+                                                                      \+    {-# INLINE sizeOfUnboxed #-};                                     \+    sizeOfUnboxed = sizeOf;                                           \+}                                                                     \++InstanceUnboxed( Char,       C#,     readWideCharArray#, writeWideCharArray#, indexWideCharArray#)+InstanceUnboxed( Int,        I#,     readIntArray#,      writeIntArray#,      indexIntArray#)+InstanceUnboxed( Int8,       I8#,    readInt8Array#,     writeInt8Array#,     indexInt8Array#)+InstanceUnboxed( Int16,      I16#,   readInt16Array#,    writeInt16Array#,    indexInt16Array#)+InstanceUnboxed( Int32,      I32#,   readInt32Array#,    writeInt32Array#,    indexInt32Array#)+InstanceUnboxed( Int64,      I64#,   readInt64Array#,    writeInt64Array#,    indexInt64Array#)+InstanceUnboxed( Word,       W#,     readWordArray#,     writeWordArray#,     indexWordArray#)+InstanceUnboxed( Word8,      W8#,    readWord8Array#,    writeWord8Array#,    indexWord8Array#)+InstanceUnboxed( Word16,     W16#,   readWord16Array#,   writeWord16Array#,   indexWord16Array#)+InstanceUnboxed( Word32,     W32#,   readWord32Array#,   writeWord32Array#,   indexWord32Array#)+InstanceUnboxed( Word64,     W64#,   readWord64Array#,   writeWord64Array#,   indexWord64Array#)+InstanceUnboxed( Float,      F#,     readFloatArray#,    writeFloatArray#,    indexFloatArray#)+InstanceUnboxed( Double,     D#,     readDoubleArray#,   writeDoubleArray#,   indexDoubleArray#)+InstanceUnboxed( (Ptr a),    Ptr,    readAddrArray#,     writeAddrArray#,     indexAddrArray#)+InstanceUnboxed( (FunPtr a), FunPtr, readAddrArray#,     writeAddrArray#,     indexAddrArray#)+InstanceUnboxed( (StablePtr a), StablePtr, readStablePtrArray#, writeStablePtrArray#, indexStablePtrArray#)+
+ Hugs/Typeable.h view
@@ -0,0 +1,70 @@+/* ----------------------------------------------------------------------------+ * Macros to help make Typeable instances.+ *+ * INSTANCE_TYPEABLEn(tc,tcname,"tc") defines+ *+ *      instance Typeable/n/ tc+ *      instance Typeable a => Typeable/n-1/ (tc a)+ *      instance (Typeable a, Typeable b) => Typeable/n-2/ (tc a b)+ *      ...+ *      instance (Typeable a1, ..., Typeable an) => Typeable (tc a1 ... an)+ * -------------------------------------------------------------------------- */++#ifndef TYPEABLE_H+#define TYPEABLE_H++#define INSTANCE_TYPEABLE0(tycon,tcname,str) \+tcname = mkTyCon str; \+instance Typeable tycon where { typeOf _ = mkTyConApp tcname [] }++#ifdef __GLASGOW_HASKELL__++/* For GHC, the extra instances follow from general instance declarations+ * defined in Data.Typeable. */++#define INSTANCE_TYPEABLE1(tycon,tcname,str) \+tcname = mkTyCon str; \+instance Typeable1 tycon where { typeOf1 _ = mkTyConApp tcname [] }++#define INSTANCE_TYPEABLE2(tycon,tcname,str) \+tcname = mkTyCon str; \+instance Typeable2 tycon where { typeOf2 _ = mkTyConApp tcname [] }++#define INSTANCE_TYPEABLE3(tycon,tcname,str) \+tcname = mkTyCon str; \+instance Typeable3 tycon where { typeOf3 _ = mkTyConApp tcname [] }++#elif defined(__HUGS__) && defined(__HUGS_VERSION__) && (__HUGS_VERSION__>=2005)++#define INSTANCE_TYPEABLE1(tycon,tcname,str) \+tcname = mkTyCon str; \+instance Typeable1 tycon where { typeOf1 _ = mkTyConApp tcname [] }; \+instance Typeable a => Typeable (tycon a) where { typeOf = typeOfDefault }++#define INSTANCE_TYPEABLE2(tycon,tcname,str) \+tcname = mkTyCon str; \+instance Typeable2 tycon where { typeOf2 _ = mkTyConApp tcname [] }; \+instance Typeable a => Typeable1 (tycon a) where { \+  typeOf1 = typeOf1Default }; \+instance (Typeable a, Typeable b) => Typeable (tycon a b) where { \+  typeOf = typeOfDefault }++#define INSTANCE_TYPEABLE3(tycon,tcname,str) \+tcname = mkTyCon str; \+instance Typeable3 tycon where { typeOf3 _ = mkTyConApp tcname [] }; \+instance Typeable a => Typeable2 (tycon a) where { \+  typeOf2 = typeOf2Default }; \+instance (Typeable a, Typeable b) => Typeable1 (tycon a b) where { \+  typeOf1 = typeOf1Default }; \+instance (Typeable a, Typeable b, Typeable c) => Typeable (tycon a b c) where { \+  typeOf = typeOfDefault }++#else++#define INSTANCE_TYPEABLE1(tycon,tcname,str)+#define INSTANCE_TYPEABLE2(tycon,tcname,str)+#define INSTANCE_TYPEABLE3(tycon,tcname,str)++#endif /* !__GLASGOW_HASKELL__ */++#endif
+ LICENSE view
@@ -0,0 +1,28 @@+Copyright (c) The University of Glasgow 2001+          (c) Bulat Ziganshin 2006++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.+2. 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.+3. Neither the name of the authro nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 AUTHORS 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 view
+ Setup.hs view
@@ -0,0 +1,5 @@+#!/usr/bin/env runhaskell++import Distribution.Simple++main = defaultMainWithHooks defaultUserHooks
+ TODO view