{-# LANGUAGE CPP #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE Rank2Types #-} ----------------------------------------------------------------------------- -- | -- Module : Data.Array.Vector.UArr -- Copyright : (c) [2001..2002] Manuel M T Chakravarty & Gabriele Keller -- (c) 2006 Manuel M T Chakravarty & Roman Leshchinskiy -- License : see libraries/ndp/LICENSE -- -- Maintainer : Roman Leshchinskiy -- Stability : internal -- Portability : non-portable (GADTS) -- -- Description --------------------------------------------------------------- -- -- This module defines unlifted arrays generically as a GADT. -- -- Slicing is implemented by each `BUArr' having the slicing information. A -- possible alternative design would be to maintain this information in -- `UArr', but not in the representations, but at the root. This may seem -- attractive at first, but seems to be more disruptive without any real -- benefits _ this is essentially, because we then need the slicing -- information at each level; ie, also at the leafs where it is sufficient -- using the current implementation. -- -- Todo ---------------------------------------------------------------------- -- #include "fusion-phases.h" module Data.Array.Vector.UArr ( -- * Array types and classes containing the admissable elements types UA, UArr, MUArr, UPrim(..), -- * Basic operations on parallel arrays lengthU, indexU, sliceU, {-extractU,-} unitsU, zipU, unzipU, fstU, sndU, newU, newDynU, newDynResU, lengthMU, newMU, readMU, writeMU, copyMU, unsafeFreezeMU, unsafeFreezeAllMU, -- * I\/O UIO(..) ) where -- standard libraries import Control.Monad (liftM, liftM2) -- For instances: import Data.Complex import GHC.Real -- friends import Data.Array.Vector.Prim.BUArr ( BUArr, MBUArr, UAE, lengthBU, indexBU, sliceBU, hGetBU, hPutBU, lengthMBU, newMBU, readMBU, writeMBU, copyMBU, unsafeFreezeMBU) import System.IO import GHC.ST import Data.Word import Data.Int import Data.Array.Vector.Prim.Debug import Data.Array.Vector.Prim.Hyperstrict infixl 9 `indexU`, `readMU` -- |Basic operations on representation types -- ----------------------------------------- -- |This type class determines the types that can be elements immutable -- unboxed arrays. The representation type of these arrays is defined by way -- of an associated type. All representation-dependent functions are methods -- of this class. -- class UA e where data UArr e data MUArr e :: * -> * -- |Yield the length of an unboxed array lengthU :: UArr e -> Int -- |Extract an element out of an immutable unboxed array indexU :: UArr e -> Int -> e -- |Restrict access to a subrange of the original array (no copying) sliceU :: UArr e -> Int -> Int -> UArr e ------------------------------------------------------------------------ -- |Yield the length of a mutable unboxed array lengthMU :: MUArr e s -> Int -- |Allocate a mutable unboxed array newMU :: Int -> ST s (MUArr e s) -- |Read an element from a mutable unboxed array readMU :: MUArr e s -> Int -> ST s e -- |Update an element in a mutable unboxed array writeMU :: MUArr e s -> Int -> e -> ST s () ------------------------------------------------------------------------ -- |Copy the contents of an immutable unboxed array into a mutable one -- from the specified position on copyMU :: MUArr e s -> Int -> UArr e -> ST s () -- |Convert a mutable into an immutable unboxed array unsafeFreezeMU :: MUArr e s -> Int -> ST s (UArr e) -- instance HS e => HS (UArr e) -- instance HS e => HS (MUArr e s) class UAE e => UPrim e where mkUAPrim :: BUArr e -> UArr e unUAPrim :: UArr e -> BUArr e mkMUAPrim :: MBUArr s e -> MUArr e s unMUAPrim :: MUArr e s -> MBUArr s e unsafeFreezeAllMU :: UA e => MUArr e s -> ST s (UArr e) unsafeFreezeAllMU marr = unsafeFreezeMU marr (lengthMU marr) -- |Creating unboxed arrays -- ------------------------ newU :: UA e => Int -> (forall s. MUArr e s -> ST s ()) -> UArr e {-# INLINE_U newU #-} newU n init = newDynU n (\ma -> init ma >> return n) newDynU :: UA e => Int -> (forall s. MUArr e s -> ST s Int) -> UArr e {-# INLINE_U newDynU #-} newDynU n init = runST (do ma <- newMU n n' <- init ma unsafeFreezeMU ma n' ) newDynResU :: UA e => Int -> (forall s. MUArr e s -> ST s (Int :*: r)) -> UArr e :*: r {-# INLINE_U newDynResU #-} newDynResU n init = runST (do ma <- newMU n n' :*: r <- init ma arr <- unsafeFreezeMU ma n' return (arr :*: r) ) -- |Basic operations on unboxed arrays -- ----------------------------------- -- |Yield an array of units -- unitsU :: Int -> UArr () {-# INLINE_STREAM unitsU #-} unitsU = UAUnit -- |Elementwise pairing of array elements. -- zipU :: (UA a, UA b) => UArr a -> UArr b -> UArr (a :*: b) {-# INLINE_STREAM zipU #-} zipU = UAProd -- |Elementwise unpairing of array elements. -- unzipU :: (UA a, UA b) => UArr (a :*: b) -> (UArr a :*: UArr b) {-# INLINE_STREAM unzipU #-} unzipU (UAProd l r) = (l :*: r) -- |Yield the first components of an array of pairs. -- fstU :: (UA a, UA b) => UArr (a :*: b) -> UArr a {-# INLINE_STREAM fstU #-} fstU (UAProd l r) = l -- |Yield the second components of an array of pairs. -- sndU :: (UA a, UA b) => UArr (a :*: b) -> UArr b {-# INLINE_STREAM sndU #-} sndU (UAProd l r) = r -- |Family of representation types -- ------------------------------- -- |Array operations on the unit representation. -- instance UA () where newtype UArr () = UAUnit Int newtype MUArr () s = MUAUnit Int lengthU (UAUnit n) = n indexU (UAUnit _) _ = () sliceU (UAUnit _) _ n = UAUnit n lengthMU (MUAUnit n) = n newMU n = return $ MUAUnit n readMU (MUAUnit _) _ = return () writeMU (MUAUnit _) _ _ = return () copyMU (MUAUnit _) _ (UAUnit _) = return () unsafeFreezeMU (MUAUnit _) n = return $ UAUnit n -- |Array operations on the pair representation. -- instance (UA a, UA b) => UA (a :*: b) where data UArr (a :*: b) = UAProd !(UArr a) !(UArr b) data MUArr (a :*: b) s = MUAProd !(MUArr a s) !(MUArr b s) -- TODO: changed from (lengthU l), as this causes problems when the length is used to -- limit the index lengthU (UAProd l r) = checkEq "lengthU" "lengths of zipped arrays differ" (lengthU l) (lengthU r) (lengthU l) {-# INLINE_U indexU #-} indexU (UAProd l r) i = indexU l i :*: indexU r i {-# INLINE_U sliceU #-} sliceU (UAProd l r) i n = UAProd (sliceU l i n) (sliceU r i n) {-# INLINE_U lengthMU #-} lengthMU (MUAProd l r) = lengthMU l {-# INLINE_U newMU #-} newMU n = do a <- newMU n b <- newMU n return $ MUAProd a b {-# INLINE_U readMU #-} readMU (MUAProd a b) i = liftM2 (:*:) (a `readMU` i) (b `readMU` i) {-# INLINE_U writeMU #-} writeMU (MUAProd a b) i (x :*: y) = do writeMU a i x writeMU b i y {-# INLINE_U copyMU #-} copyMU (MUAProd ma mb) i (UAProd a b) = do copyMU ma i a copyMU mb i b {-# INLINE_U unsafeFreezeMU #-} unsafeFreezeMU (MUAProd a b) n = do a' <- unsafeFreezeMU a n b' <- unsafeFreezeMU b n return $ UAProd a' b' {- -- |Selector for immutable arrays of sums -- data USel = USel { selUS :: !(BUArr Bool), -- selector (False => left) lidxUS :: !(BUArr Int), -- left indices ridxUS :: !(BUArr Int) -- right indices } --instance HS USel -- |Selector for mutable arrays of sums -- data MUSel s = MUSel { selMUS :: !(MBUArr s Bool), -- selector (False => left) lidxMUS :: !(MBUArr s Int), -- left indices ridxMUS :: !(MBUArr s Int) -- right indices } --instance HS (MUSel s) -- |Array operations on the sum representation -- instance (UA a, UA b) => UA (a :+: b) where lengthU (UASum sel _ _) = lengthBU (selUS sel) {-# INLINE_U indexU #-} indexU (UASum sel l r) i = if (selUS sel)`indexBU`i then Inr $ indexU r i else Inl $ indexU l i {-# INLINE_U sliceU #-} sliceU (UASum sel l r) i n = let sel' = sliceBU (selUS sel) i n li = lidxUS sel`indexBU`i ri = ridxUS sel`indexBU`i lidx = mapBU (subtract li) $ sliceBU (lidxUS sel) i n ridx = mapBU (subtract ri) $ sliceBU (ridxUS sel) i n (ln :*: rn) = if n == 0 then (0 :*: 0) else (lidx`indexBU`(n - 1) :*: ridx`indexBU`(n - 1)) in UASum (USel sel' lidx ridx) (sliceU l li ln) (sliceU r ri rn) {-# INLINE_U extractU #-} extractU (UASum sel l r) i n = let sel' = extractBU (selUS sel) i n li = lidxUS sel`indexBU`i ri = ridxUS sel`indexBU`i lidx = mapBU (subtract li) $ sliceBU (lidxUS sel) i n ridx = mapBU (subtract ri) $ sliceBU (ridxUS sel) i n (ln :*: rn) = if n == 0 then (0 :*: 0) else (lidx`indexBU`(n - 1) :*: ridx`indexBU`(n - 1)) in UASum (USel sel' lidx ridx) (extractU l li ln) (extractU r ri rn) instance (MUA a, MUA b) => MUA (a :+: b) where {-# INLINE_U newMU #-} newMU n = do sel <- newMBU n lidx <- newMBU n ridx <- newMBU n a <- newMU n b <- newMU n return $ MUASum (MUSel sel lidx ridx) a b {-# INLINE_U writeMU #-} writeMU (MUASum sel l r) i (Inl x) = do let lidx = lidxMUS sel ridx = ridxMUS sel writeMBU (selMUS sel) i False li <- if i == 0 then return 0 else liftM (+ 1) $ lidx`readMBU`(i - 1) ri <- if i == 0 then return 0 else ridx`readMBU`(i - 1) writeMBU lidx i li writeMBU ridx i ri writeMU l li x writeMU (MUASum sel l r) i (Inr x) = do let lidx = lidxMUS sel ridx = ridxMUS sel writeMBU (selMUS sel) i True li <- if i == 0 then return 0 else lidx`readMBU`(i - 1) ri <- if i == 0 then return 0 else liftM (+ 1) $ ridx`readMBU`(i - 1) writeMBU lidx i li writeMBU ridx i ri writeMU r ri x --FIXME: that works only when the array is constructed left to right, but --not for something like permutations {-# INLINE_U unsafeFreezeMU #-} unsafeFreezeMU (MUASum sel l r) n = do sel' <- unsafeFreezeMBU (selMUS sel) n lidx <- unsafeFreezeMBU (lidxMUS sel) n ridx <- unsafeFreezeMBU (ridxMUS sel) n let ln = if n == 0 then 0 else lidx`indexBU`(n - 1) rn = if n == 0 then 0 else ridx`indexBU`(n - 1) l' <- unsafeFreezeMU l ln r' <- unsafeFreezeMU r rn return $ UASum (USel sel' lidx ridx) l' r' -} -- |Array operations on unboxed arrays -- - -- -- NB: We use instances for all possible unboxed types instead of re-using the -- overloading provided by UAE to avoid having to store the UAE dictionary -- in `UAPrimU'. primLengthU :: UPrim e => UArr e -> Int {-# INLINE_U primLengthU #-} primLengthU = lengthBU . unUAPrim primIndexU :: UPrim e => UArr e -> Int -> e {-# INLINE_U primIndexU #-} primIndexU = indexBU . unUAPrim primSliceU :: UPrim e => UArr e -> Int -> Int -> UArr e {-# INLINE_U primSliceU #-} primSliceU arr i = mkUAPrim . sliceBU (unUAPrim arr) i primLengthMU :: UPrim e => MUArr e s -> Int {-# INLINE_U primLengthMU #-} primLengthMU = lengthMBU . unMUAPrim primNewMU :: UPrim e => Int -> ST s (MUArr e s) {-# INLINE_U primNewMU #-} primNewMU = liftM mkMUAPrim . newMBU primReadMU :: UPrim e => MUArr e s -> Int -> ST s e {-# INLINE_U primReadMU #-} primReadMU = readMBU . unMUAPrim primWriteMU :: UPrim e => MUArr e s -> Int -> e -> ST s () {-# INLINE_U primWriteMU #-} primWriteMU = writeMBU . unMUAPrim primCopyMU :: UPrim e => MUArr e s -> Int -> UArr e -> ST s () {-# INLINE_U primCopyMU #-} primCopyMU ma i = copyMBU (unMUAPrim ma) i . unUAPrim primUnsafeFreezeMU :: UPrim e => MUArr e s -> Int -> ST s (UArr e) {-# INLINE_U primUnsafeFreezeMU #-} primUnsafeFreezeMU ma = liftM mkUAPrim . unsafeFreezeMBU (unMUAPrim ma) instance UPrim Bool where mkUAPrim = UABool unUAPrim (UABool arr) = arr mkMUAPrim = MUABool unMUAPrim (MUABool arr) = arr instance UA Bool where newtype UArr Bool = UABool (BUArr Bool) newtype MUArr Bool s = MUABool (MBUArr s Bool) lengthU = primLengthU indexU = primIndexU sliceU = primSliceU lengthMU = primLengthMU newMU = primNewMU readMU = primReadMU writeMU = primWriteMU copyMU = primCopyMU unsafeFreezeMU = primUnsafeFreezeMU instance UPrim Char where mkUAPrim = UAChar unUAPrim (UAChar arr) = arr mkMUAPrim = MUAChar unMUAPrim (MUAChar arr) = arr instance UA Char where newtype UArr Char = UAChar !(BUArr Char) newtype MUArr Char s = MUAChar !(MBUArr s Char) lengthU = primLengthU indexU = primIndexU sliceU = primSliceU lengthMU = primLengthMU newMU = primNewMU readMU = primReadMU writeMU = primWriteMU copyMU = primCopyMU unsafeFreezeMU = primUnsafeFreezeMU instance UPrim Int where mkUAPrim = UAInt unUAPrim (UAInt arr) = arr mkMUAPrim = MUAInt unMUAPrim (MUAInt arr) = arr instance UA Int where newtype UArr Int = UAInt !(BUArr Int) newtype MUArr Int s = MUAInt !(MBUArr s Int) lengthU = primLengthU indexU = primIndexU sliceU = primSliceU lengthMU = primLengthMU newMU = primNewMU readMU = primReadMU writeMU = primWriteMU copyMU = primCopyMU unsafeFreezeMU = primUnsafeFreezeMU -- FIXME: For now, we assume that Int writes are atomic but we should really -- configure this. instance UPrim Word where mkUAPrim = UAWord unUAPrim (UAWord arr) = arr mkMUAPrim = MUAWord unMUAPrim (MUAWord arr) = arr instance UA Word where newtype UArr Word = UAWord !(BUArr Word) newtype MUArr Word s = MUAWord !(MBUArr s Word) lengthU = primLengthU indexU = primIndexU sliceU = primSliceU lengthMU = primLengthMU newMU = primNewMU readMU = primReadMU writeMU = primWriteMU copyMU = primCopyMU unsafeFreezeMU = primUnsafeFreezeMU -- FIXME: For now, we assume that Word writes are atomic but we should really -- configure this. instance UPrim Float where mkUAPrim = UAFloat unUAPrim (UAFloat arr) = arr mkMUAPrim = MUAFloat unMUAPrim (MUAFloat arr) = arr instance UA Float where newtype UArr Float = UAFloat !(BUArr Float) newtype MUArr Float s = MUAFloat !(MBUArr s Float) lengthU = primLengthU indexU = primIndexU sliceU = primSliceU lengthMU = primLengthMU newMU = primNewMU readMU = primReadMU writeMU = primWriteMU copyMU = primCopyMU unsafeFreezeMU = primUnsafeFreezeMU instance UPrim Double where mkUAPrim = UADouble unUAPrim (UADouble arr) = arr mkMUAPrim = MUADouble unMUAPrim (MUADouble arr) = arr instance UA Double where newtype UArr Double = UADouble !(BUArr Double) newtype MUArr Double s = MUADouble !(MBUArr s Double) lengthU = primLengthU indexU = primIndexU sliceU = primSliceU lengthMU = primLengthMU newMU = primNewMU readMU = primReadMU writeMU = primWriteMU copyMU = primCopyMU unsafeFreezeMU = primUnsafeFreezeMU instance UPrim Word8 where mkUAPrim = UAWord8 unUAPrim (UAWord8 arr) = arr mkMUAPrim = MUAWord8 unMUAPrim (MUAWord8 arr) = arr instance UA Word8 where newtype UArr Word8 = UAWord8 !(BUArr Word8) newtype MUArr Word8 s = MUAWord8 !(MBUArr s Word8) lengthU = primLengthU indexU = primIndexU sliceU = primSliceU lengthMU = primLengthMU newMU = primNewMU readMU = primReadMU writeMU = primWriteMU copyMU = primCopyMU unsafeFreezeMU = primUnsafeFreezeMU -- FIXME: For now, we assume that Word8 writes are atomic but we should really -- configure this. instance UPrim Word16 where mkUAPrim = UAWord16 unUAPrim (UAWord16 arr) = arr mkMUAPrim = MUAWord16 unMUAPrim (MUAWord16 arr) = arr instance UA Word16 where newtype UArr Word16 = UAWord16 !(BUArr Word16) newtype MUArr Word16 s = MUAWord16 !(MBUArr s Word16) lengthU = primLengthU indexU = primIndexU sliceU = primSliceU lengthMU = primLengthMU newMU = primNewMU readMU = primReadMU writeMU = primWriteMU copyMU = primCopyMU unsafeFreezeMU = primUnsafeFreezeMU instance UPrim Word32 where mkUAPrim = UAWord32 unUAPrim (UAWord32 arr) = arr mkMUAPrim = MUAWord32 unMUAPrim (MUAWord32 arr) = arr instance UA Word32 where newtype UArr Word32 = UAWord32 !(BUArr Word32) newtype MUArr Word32 s = MUAWord32 !(MBUArr s Word32) lengthU = primLengthU indexU = primIndexU sliceU = primSliceU lengthMU = primLengthMU newMU = primNewMU readMU = primReadMU writeMU = primWriteMU copyMU = primCopyMU unsafeFreezeMU = primUnsafeFreezeMU instance UPrim Word64 where mkUAPrim = UAWord64 unUAPrim (UAWord64 arr) = arr mkMUAPrim = MUAWord64 unMUAPrim (MUAWord64 arr) = arr instance UA Word64 where newtype UArr Word64 = UAWord64 !(BUArr Word64) newtype MUArr Word64 s = MUAWord64 !(MBUArr s Word64) lengthU = primLengthU indexU = primIndexU sliceU = primSliceU lengthMU = primLengthMU newMU = primNewMU readMU = primReadMU writeMU = primWriteMU copyMU = primCopyMU unsafeFreezeMU = primUnsafeFreezeMU instance UPrim Int8 where mkUAPrim = UAInt8 unUAPrim (UAInt8 arr) = arr mkMUAPrim = MUAInt8 unMUAPrim (MUAInt8 arr) = arr instance UA Int8 where newtype UArr Int8 = UAInt8 !(BUArr Int8) newtype MUArr Int8 s = MUAInt8 !(MBUArr s Int8) lengthU = primLengthU indexU = primIndexU sliceU = primSliceU lengthMU = primLengthMU newMU = primNewMU readMU = primReadMU writeMU = primWriteMU copyMU = primCopyMU unsafeFreezeMU = primUnsafeFreezeMU -- FIXME: For now, we assume that Int8 writes are atomic but we should really -- configure this. instance UPrim Int16 where mkUAPrim = UAInt16 unUAPrim (UAInt16 arr) = arr mkMUAPrim = MUAInt16 unMUAPrim (MUAInt16 arr) = arr instance UA Int16 where newtype UArr Int16 = UAInt16 !(BUArr Int16) newtype MUArr Int16 s = MUAInt16 !(MBUArr s Int16) lengthU = primLengthU indexU = primIndexU sliceU = primSliceU lengthMU = primLengthMU newMU = primNewMU readMU = primReadMU writeMU = primWriteMU copyMU = primCopyMU unsafeFreezeMU = primUnsafeFreezeMU instance UPrim Int32 where mkUAPrim = UAInt32 unUAPrim (UAInt32 arr) = arr mkMUAPrim = MUAInt32 unMUAPrim (MUAInt32 arr) = arr instance UA Int32 where newtype UArr Int32 = UAInt32 !(BUArr Int32) newtype MUArr Int32 s = MUAInt32 !(MBUArr s Int32) lengthU = primLengthU indexU = primIndexU sliceU = primSliceU lengthMU = primLengthMU newMU = primNewMU readMU = primReadMU writeMU = primWriteMU copyMU = primCopyMU unsafeFreezeMU = primUnsafeFreezeMU instance UPrim Int64 where mkUAPrim = UAInt64 unUAPrim (UAInt64 arr) = arr mkMUAPrim = MUAInt64 unMUAPrim (MUAInt64 arr) = arr instance UA Int64 where newtype UArr Int64 = UAInt64 !(BUArr Int64) newtype MUArr Int64 s = MUAInt64 !(MBUArr s Int64) lengthU = primLengthU indexU = primIndexU sliceU = primSliceU lengthMU = primLengthMU newMU = primNewMU readMU = primReadMU writeMU = primWriteMU copyMU = primCopyMU unsafeFreezeMU = primUnsafeFreezeMU ------------------------------------------------------------------------ -- TODO could use a single array of 'a', doubly packed instance (RealFloat a, UA a) => UA (Complex a) where newtype UArr (Complex a) = UAComplex !(UArr (a :*: a)) newtype MUArr (Complex a) s = MUAComplex !(MUArr (a :*: a) s) lengthU (UAComplex arr) = lengthU arr indexU (UAComplex arr) i = case indexU arr i of (a :*: b) -> a :+ b sliceU (UAComplex arr) i n = UAComplex (sliceU arr i n) lengthMU (MUAComplex arr) = lengthMU arr newMU n = return . MUAComplex =<< newMU n readMU (MUAComplex arr) n = do (a :*: b) <- readMU arr n; return (a :+ b) writeMU (MUAComplex arr) i (x :+ y) = writeMU arr i (x :*: y) copyMU (MUAComplex mua) n (UAComplex ua) = copyMU mua n ua unsafeFreezeMU (MUAComplex arr) n = do arr' <- unsafeFreezeMU arr n; return (UAComplex arr') instance (Integral a, UA a) => UA (Ratio a) where newtype UArr (Ratio a) = UARatio !(UArr (a :*: a)) newtype MUArr (Ratio a) s = MUARatio !(MUArr (a :*: a) s) lengthU (UARatio arr) = lengthU arr indexU (UARatio arr) i = case indexU arr i of (a :*: b) -> a % b sliceU (UARatio arr) i n = UARatio (sliceU arr i n) lengthMU (MUARatio arr) = lengthMU arr newMU n = return . MUARatio =<< newMU n readMU (MUARatio arr) n = do (a :*: b) <- readMU arr n; return (a % b) writeMU (MUARatio arr) i (n :% d) = writeMU arr i (n :*: d) copyMU (MUARatio mua) n (UARatio ua) = copyMU mua n ua unsafeFreezeMU (MUARatio arr) n = do arr' <- unsafeFreezeMU arr n; return (UARatio arr') ------------------------------------------------------------------------ -- * I\/O -- ----- class UA a => UIO a where hPutU :: Handle -> UArr a -> IO () hGetU :: Handle -> IO (UArr a) primPutU :: UPrim a => Handle -> UArr a -> IO () primPutU h = hPutBU h . unUAPrim primGetU :: UPrim a => Handle -> IO (UArr a) primGetU = liftM mkUAPrim . hGetBU ------------------------------------------------------------------------ instance UIO Bool where hPutU = primPutU; hGetU = primGetU instance UIO Char where hPutU = primPutU; hGetU = primGetU instance UIO Int where hPutU = primPutU; hGetU = primGetU instance UIO Word where hPutU = primPutU; hGetU = primGetU instance UIO Float where hPutU = primPutU; hGetU = primGetU instance UIO Double where hPutU = primPutU; hGetU = primGetU instance UIO Word8 where hPutU = primPutU; hGetU = primGetU instance UIO Word16 where hPutU = primPutU; hGetU = primGetU instance UIO Word32 where hPutU = primPutU; hGetU = primGetU instance UIO Word64 where hPutU = primPutU; hGetU = primGetU instance UIO Int8 where hPutU = primPutU; hGetU = primGetU instance UIO Int16 where hPutU = primPutU; hGetU = primGetU instance UIO Int32 where hPutU = primPutU; hGetU = primGetU instance UIO Int64 where hPutU = primPutU; hGetU = primGetU ------------------------------------------------------------------------ instance (UIO a, UIO b) => UIO (a :*: b) where hPutU h (UAProd xs ys) = do hPutU h xs hPutU h ys hGetU h = do xs <- hGetU h ys <- hGetU h return (UAProd xs ys) instance (RealFloat a, UIO a) => UIO (Complex a) where hPutU h (UAComplex arr) = hPutU h arr hGetU h = do arr <- hGetU h return (UAComplex arr) instance (Integral a, UIO a) => UIO (Ratio a) where hPutU h (UARatio arr) = hPutU h arr hGetU h = do arr <- hGetU h return (UARatio arr)