{-# LANGUAGE DefaultSignatures, FlexibleContexts, FlexibleInstances, GADTs, MultiParamTypeClasses,
             TypeFamilies, UndecidableInstances #-}
{-|
== Arrays

Stuff to make it easier to work with arrays from the array package, especially when it comes to
unboxed arrays. If the vector package is available, just use that.

-}

{-
Implementation notes:
* The problem: Unboxed array types (UArray, STUArray, IOUArray) have the element type role as
  nominal (https://gitlab.haskell.org/ghc/ghc/-/issues/9220). This makes it impossible to newtype
  derive IArray and MArray instances. And it's a PITA to write them manually for every newtype.
  No one wants to write 40 lines of instances each for Sum Int, Max Int, Mod 1000000007 Int.
* The solution: Use a newtype wrapper and an iso class (a bit like Vector.Unboxed.IsoUnbox). This
  still requires ~30 lines of code, but only once. The typeclass also makes it useful for more than
  just newtypes. This is the cleanest approach I got so far. If there is a better way, I would love
  to hear of it.
* We use an associated type over fundeps (class Unbox a b | a -> b) because Arr would then need to
  be Arr b arr i a and you would have to specify b when using it even though a determines b.
* Indexing is as fast as the underlying representation but construction via listArray and array are
  known to be slower. See ArrayBench.hs. TODO: Figure out why and fix it.
* unsafeAccum and unsafeAccumArray are optional but explicity error for Arr2 because the default
  definitions use STArray. This is horribly slow with unboxed arrays. Better error than TLE.
* TODO: Implement freeze and unsafeFreeze.
-}

module Array
    ( Unbox(..)
    , Arr
    , UArr
    , IOUArr
    , STUArr
    , Arr2
    , UArr2
    , UArr3
    , UArr4
    , STUArr2
    , STUArr3
    , STUArr4
    , IOUArr2
    , IOUArr3
    , IOUArr4
    ) where

import Control.DeepSeq
import Data.Array.Base
import Data.Array.IO
import Data.Coerce
import Data.Semigroup

--------------------------------------------------------------------------------
-- Unbox and Arr

class Unbox a where
    type Unboxed a
    toU :: a -> Unboxed a
    default toU :: Coercible a (Unboxed a) => a -> Unboxed a
    toU = a -> Unboxed a
coerce
    frU :: Unboxed a -> a
    default frU :: Coercible (Unboxed a) a => Unboxed a -> a
    frU = Unboxed a -> a
coerce

-- | Array type for element types isomorphic to other element types with existing array support.
-- Primarily intended as a way to get unboxed arrays.
-- As an example, if you have "newtype N = N Int", define "instance Unbox N where type Unboxed N = Int"
-- and use UArr i N as an unboxed array for N. This is a lot more performant than a boxed Array i N.
-- Also works with mutable arrays, IOUArr and STUArr.
newtype Arr arr i a = Arr { Arr arr i a -> arr i (Unboxed a)
unArr :: arr i (Unboxed a) }

instance (Unbox a, IArray arr (Unboxed a)) => IArray (Arr arr) a where
    bounds :: Arr arr i a -> (i, i)
bounds                     = arr i (Unboxed a) -> (i, i)
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> (i, i)
bounds (arr i (Unboxed a) -> (i, i))
-> (Arr arr i a -> arr i (Unboxed a)) -> Arr arr i a -> (i, i)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Arr arr i a -> arr i (Unboxed a)
forall (arr :: * -> * -> *) i a. Arr arr i a -> arr i (Unboxed a)
unArr
    numElements :: Arr arr i a -> Int
numElements                = arr i (Unboxed a) -> Int
forall (a :: * -> * -> *) e i. (IArray a e, Ix i) => a i e -> Int
numElements (arr i (Unboxed a) -> Int)
-> (Arr arr i a -> arr i (Unboxed a)) -> Arr arr i a -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Arr arr i a -> arr i (Unboxed a)
forall (arr :: * -> * -> *) i a. Arr arr i a -> arr i (Unboxed a)
unArr
    unsafeArray :: (i, i) -> [(Int, a)] -> Arr arr i a
unsafeArray (i, i)
b [(Int, a)]
ixs          = arr i (Unboxed a) -> Arr arr i a
forall (arr :: * -> * -> *) i a. arr i (Unboxed a) -> Arr arr i a
Arr ((i, i) -> [(Int, Unboxed a)] -> arr i (Unboxed a)
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
(i, i) -> [(Int, e)] -> a i e
unsafeArray (i, i)
b (((Int, a) -> (Int, Unboxed a)) -> [(Int, a)] -> [(Int, Unboxed a)]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> Unboxed a) -> (Int, a) -> (Int, Unboxed a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Unboxed a
forall a. Unbox a => a -> Unboxed a
toU) [(Int, a)]
ixs))
    unsafeAt :: Arr arr i a -> Int -> a
unsafeAt Arr arr i a
a Int
i               = Unboxed a -> a
forall a. Unbox a => Unboxed a -> a
frU (arr i (Unboxed a) -> Int -> Unboxed a
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> Int -> e
unsafeAt (Arr arr i a -> arr i (Unboxed a)
forall (arr :: * -> * -> *) i a. Arr arr i a -> arr i (Unboxed a)
unArr Arr arr i a
a) Int
i)
    unsafeReplace :: Arr arr i a -> [(Int, a)] -> Arr arr i a
unsafeReplace Arr arr i a
a [(Int, a)]
ixs        = arr i (Unboxed a) -> Arr arr i a
forall (arr :: * -> * -> *) i a. arr i (Unboxed a) -> Arr arr i a
Arr (arr i (Unboxed a) -> [(Int, Unboxed a)] -> arr i (Unboxed a)
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> [(Int, e)] -> a i e
unsafeReplace (Arr arr i a -> arr i (Unboxed a)
forall (arr :: * -> * -> *) i a. Arr arr i a -> arr i (Unboxed a)
unArr Arr arr i a
a) (((Int, a) -> (Int, Unboxed a)) -> [(Int, a)] -> [(Int, Unboxed a)]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> Unboxed a) -> (Int, a) -> (Int, Unboxed a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Unboxed a
forall a. Unbox a => a -> Unboxed a
toU) [(Int, a)]
ixs))
    unsafeAccum :: (a -> e' -> a) -> Arr arr i a -> [(Int, e')] -> Arr arr i a
unsafeAccum a -> e' -> a
f Arr arr i a
a [(Int, e')]
iys        = arr i (Unboxed a) -> Arr arr i a
forall (arr :: * -> * -> *) i a. arr i (Unboxed a) -> Arr arr i a
Arr ((Unboxed a -> e' -> Unboxed a)
-> arr i (Unboxed a) -> [(Int, e')] -> arr i (Unboxed a)
forall (a :: * -> * -> *) e i e'.
(IArray a e, Ix i) =>
(e -> e' -> e) -> a i e -> [(Int, e')] -> a i e
unsafeAccum (\Unboxed a
x e'
y -> a -> Unboxed a
forall a. Unbox a => a -> Unboxed a
toU (a -> e' -> a
f (Unboxed a -> a
forall a. Unbox a => Unboxed a -> a
frU Unboxed a
x) e'
y)) (Arr arr i a -> arr i (Unboxed a)
forall (arr :: * -> * -> *) i a. Arr arr i a -> arr i (Unboxed a)
unArr Arr arr i a
a) [(Int, e')]
iys)
    unsafeAccumArray :: (a -> e' -> a) -> a -> (i, i) -> [(Int, e')] -> Arr arr i a
unsafeAccumArray a -> e' -> a
f a
x (i, i)
b [(Int, e')]
iys = arr i (Unboxed a) -> Arr arr i a
forall (arr :: * -> * -> *) i a. arr i (Unboxed a) -> Arr arr i a
Arr ((Unboxed a -> e' -> Unboxed a)
-> Unboxed a -> (i, i) -> [(Int, e')] -> arr i (Unboxed a)
forall (a :: * -> * -> *) e i e'.
(IArray a e, Ix i) =>
(e -> e' -> e) -> e -> (i, i) -> [(Int, e')] -> a i e
unsafeAccumArray (\Unboxed a
x e'
y -> a -> Unboxed a
forall a. Unbox a => a -> Unboxed a
toU (a -> e' -> a
f (Unboxed a -> a
forall a. Unbox a => Unboxed a -> a
frU Unboxed a
x) e'
y)) (a -> Unboxed a
forall a. Unbox a => a -> Unboxed a
toU a
x) (i, i)
b [(Int, e')]
iys)

instance (IArray (Arr arr) a, Ix i, Show i, Show a) => Show (Arr arr i a) where
    showsPrec :: Int -> Arr arr i a -> ShowS
showsPrec = Int -> Arr arr i a -> ShowS
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i, Show i, Show e) =>
Int -> a i e -> ShowS
showsIArray

instance (Unbox a, Monad m, MArray marr (Unboxed a) m) => MArray (Arr marr) a m where
    getBounds :: Arr marr i a -> m (i, i)
getBounds         = marr i (Unboxed a) -> m (i, i)
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> m (i, i)
getBounds (marr i (Unboxed a) -> m (i, i))
-> (Arr marr i a -> marr i (Unboxed a)) -> Arr marr i a -> m (i, i)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Arr marr i a -> marr i (Unboxed a)
forall (arr :: * -> * -> *) i a. Arr arr i a -> arr i (Unboxed a)
unArr
    getNumElements :: Arr marr i a -> m Int
getNumElements    = marr i (Unboxed a) -> m Int
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> m Int
getNumElements (marr i (Unboxed a) -> m Int)
-> (Arr marr i a -> marr i (Unboxed a)) -> Arr marr i a -> m Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Arr marr i a -> marr i (Unboxed a)
forall (arr :: * -> * -> *) i a. Arr arr i a -> arr i (Unboxed a)
unArr
    unsafeNewArray_ :: (i, i) -> m (Arr marr i a)
unsafeNewArray_   = (marr i (Unboxed a) -> Arr marr i a)
-> m (marr i (Unboxed a)) -> m (Arr marr i a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap marr i (Unboxed a) -> Arr marr i a
forall (arr :: * -> * -> *) i a. arr i (Unboxed a) -> Arr arr i a
Arr (m (marr i (Unboxed a)) -> m (Arr marr i a))
-> ((i, i) -> m (marr i (Unboxed a))) -> (i, i) -> m (Arr marr i a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (i, i) -> m (marr i (Unboxed a))
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
(i, i) -> m (a i e)
unsafeNewArray_
    newArray_ :: (i, i) -> m (Arr marr i a)
newArray_         = (marr i (Unboxed a) -> Arr marr i a)
-> m (marr i (Unboxed a)) -> m (Arr marr i a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap marr i (Unboxed a) -> Arr marr i a
forall (arr :: * -> * -> *) i a. arr i (Unboxed a) -> Arr arr i a
Arr (m (marr i (Unboxed a)) -> m (Arr marr i a))
-> ((i, i) -> m (marr i (Unboxed a))) -> (i, i) -> m (Arr marr i a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (i, i) -> m (marr i (Unboxed a))
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
(i, i) -> m (a i e)
newArray_
    unsafeRead :: Arr marr i a -> Int -> m a
unsafeRead Arr marr i a
a Int
i    = (Unboxed a -> a) -> m (Unboxed a) -> m a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Unboxed a -> a
forall a. Unbox a => Unboxed a -> a
frU (marr i (Unboxed a) -> Int -> m (Unboxed a)
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> Int -> m e
unsafeRead (Arr marr i a -> marr i (Unboxed a)
forall (arr :: * -> * -> *) i a. Arr arr i a -> arr i (Unboxed a)
unArr Arr marr i a
a) Int
i)
    unsafeWrite :: Arr marr i a -> Int -> a -> m ()
unsafeWrite Arr marr i a
a Int
i a
x = marr i (Unboxed a) -> Int -> Unboxed a -> m ()
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> Int -> e -> m ()
unsafeWrite (Arr marr i a -> marr i (Unboxed a)
forall (arr :: * -> * -> *) i a. Arr arr i a -> arr i (Unboxed a)
unArr Arr marr i a
a) Int
i (a -> Unboxed a
forall a. Unbox a => a -> Unboxed a
toU a
x)

type UArr = Arr UArray
type IOUArr = Arr IOUArray
type STUArr s = Arr (STUArray s)

instance Unbox (Sum a) where
    type Unboxed (Sum a) = a

instance Unbox (Min a) where
    type Unboxed (Min a) = a

instance Unbox (Max a) where
    type Unboxed (Max a) = a

--------------------------------------------------------------------------------
-- Arr2

-- | Arrays for 2-tuples
-- Primarily intended as a way to get unboxed arrays.
-- If a and b can be put in UArrays, UArr2 i (a,b) works as an unboxed array for (a,b).
-- This is a lot more performant than a boxed Array i (a,b). Also works with mutable arrays, STUArr2
-- and IOUArr2.
-- Can be nested to get UArr3, UArr4, etc. Use with Unbox and Arr to store your own types.
data Arr2 arra arrb i ab where
    Arr2 :: !(arra i a) -> !(arrb i b) -> Arr2 arra arrb i (a, b)

instance (IArray arra a, IArray arrb b) => IArray (Arr2 arra arrb) (a, b) where
    bounds :: Arr2 arra arrb i (a, b) -> (i, i)
bounds (Arr2 arra i a
xa arrb i b
_)              = arra i a -> (i, i)
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> (i, i)
bounds arra i a
xa
    numElements :: Arr2 arra arrb i (a, b) -> Int
numElements (Arr2 arra i a
xa arrb i b
_)         = arra i a -> Int
forall (a :: * -> * -> *) e i. (IArray a e, Ix i) => a i e -> Int
numElements arra i a
xa
    unsafeArray :: (i, i) -> [(Int, (a, b))] -> Arr2 arra arrb i (a, b)
unsafeArray (i, i)
b [(Int, (a, b))]
ixys              = arra i a -> arrb i b -> Arr2 arra arrb i (a, b)
forall (arra :: * -> * -> *) i a (arrb :: * -> * -> *) b.
arra i a -> arrb i b -> Arr2 arra arrb i (a, b)
Arr2 ((i, i) -> [(Int, a)] -> arra i a
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
(i, i) -> [(Int, e)] -> a i e
unsafeArray (i, i)
b (((Int, (a, b)) -> (Int, a)) -> [(Int, (a, b))] -> [(Int, a)]
forall a b. (a -> b) -> [a] -> [b]
map (((a, b) -> a) -> (Int, (a, b)) -> (Int, a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, b) -> a
forall a b. (a, b) -> a
fst) [(Int, (a, b))]
ixys)) ((i, i) -> [(Int, b)] -> arrb i b
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
(i, i) -> [(Int, e)] -> a i e
unsafeArray (i, i)
b (((Int, (a, b)) -> (Int, b)) -> [(Int, (a, b))] -> [(Int, b)]
forall a b. (a -> b) -> [a] -> [b]
map (((a, b) -> b) -> (Int, (a, b)) -> (Int, b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, b) -> b
forall a b. (a, b) -> b
snd) [(Int, (a, b))]
ixys))
    unsafeAt :: Arr2 arra arrb i (a, b) -> Int -> (a, b)
unsafeAt (Arr2 arra i a
xa arrb i b
ya) Int
i         = (arra i a -> Int -> a
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> Int -> e
unsafeAt arra i a
xa Int
i, arrb i b -> Int -> b
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> Int -> e
unsafeAt arrb i b
ya Int
i)
    unsafeReplace :: Arr2 arra arrb i (a, b)
-> [(Int, (a, b))] -> Arr2 arra arrb i (a, b)
unsafeReplace (Arr2 arra i a
xa arrb i b
ya) [(Int, (a, b))]
ixys = arra i a -> arrb i b -> Arr2 arra arrb i (a, b)
forall (arra :: * -> * -> *) i a (arrb :: * -> * -> *) b.
arra i a -> arrb i b -> Arr2 arra arrb i (a, b)
Arr2 (arra i a -> [(Int, a)] -> arra i a
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> [(Int, e)] -> a i e
unsafeReplace arra i a
xa (((Int, (a, b)) -> (Int, a)) -> [(Int, (a, b))] -> [(Int, a)]
forall a b. (a -> b) -> [a] -> [b]
map (((a, b) -> a) -> (Int, (a, b)) -> (Int, a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, b) -> a
forall a b. (a, b) -> a
fst) [(Int, (a, b))]
ixys)) (arrb i b -> [(Int, b)] -> arrb i b
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> [(Int, e)] -> a i e
unsafeReplace arrb i b
ya (((Int, (a, b)) -> (Int, b)) -> [(Int, (a, b))] -> [(Int, b)]
forall a b. (a -> b) -> [a] -> [b]
map (((a, b) -> b) -> (Int, (a, b)) -> (Int, b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a, b) -> b
forall a b. (a, b) -> b
snd) [(Int, (a, b))]
ixys))
    unsafeAccum :: ((a, b) -> e' -> (a, b))
-> Arr2 arra arrb i (a, b)
-> [(Int, e')]
-> Arr2 arra arrb i (a, b)
unsafeAccum                     = String
-> ((a, b) -> e' -> (a, b))
-> Arr2 arra arrb i (a, b)
-> [(Int, e')]
-> Arr2 arra arrb i (a, b)
forall a. HasCallStack => String -> a
error String
"Arr2 unsafeAccum: not implemented"
    unsafeAccumArray :: ((a, b) -> e' -> (a, b))
-> (a, b) -> (i, i) -> [(Int, e')] -> Arr2 arra arrb i (a, b)
unsafeAccumArray                = String
-> ((a, b) -> e' -> (a, b))
-> (a, b)
-> (i, i)
-> [(Int, e')]
-> Arr2 arra arrb i (a, b)
forall a. HasCallStack => String -> a
error String
"Arr2 unsafeAccumArray: not implemented"

instance (IArray (Arr2 arra arrb) ab, Ix i, Show i, Show ab) => Show (Arr2 arra arrb i ab) where
    showsPrec :: Int -> Arr2 arra arrb i ab -> ShowS
showsPrec = Int -> Arr2 arra arrb i ab -> ShowS
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i, Show i, Show e) =>
Int -> a i e -> ShowS
showsIArray

instance (Monad m, MArray marra a m, MArray marrb b m) => MArray (Arr2 marra marrb) (a, b) m where
    getBounds :: Arr2 marra marrb i (a, b) -> m (i, i)
getBounds (Arr2 marra i a
xa marrb i b
_)             = marra i a -> m (i, i)
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> m (i, i)
getBounds marra i a
xa
    getNumElements :: Arr2 marra marrb i (a, b) -> m Int
getNumElements (Arr2 marra i a
xa marrb i b
_)        = marra i a -> m Int
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> m Int
getNumElements marra i a
xa
    unsafeNewArray_ :: (i, i) -> m (Arr2 marra marrb i (a, b))
unsafeNewArray_ (i, i)
b                 = marra i a -> marrb i b -> Arr2 marra marrb i (a, b)
forall (arra :: * -> * -> *) i a (arrb :: * -> * -> *) b.
arra i a -> arrb i b -> Arr2 arra arrb i (a, b)
Arr2 (marra i a -> marrb i b -> Arr2 marra marrb i (a, b))
-> m (marra i a) -> m (marrb i b -> Arr2 marra marrb i (a, b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (i, i) -> m (marra i a)
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
(i, i) -> m (a i e)
unsafeNewArray_ (i, i)
b m (marrb i b -> Arr2 marra marrb i (a, b))
-> m (marrb i b) -> m (Arr2 marra marrb i (a, b))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (i, i) -> m (marrb i b)
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
(i, i) -> m (a i e)
unsafeNewArray_ (i, i)
b
    newArray_ :: (i, i) -> m (Arr2 marra marrb i (a, b))
newArray_ (i, i)
b                       = marra i a -> marrb i b -> Arr2 marra marrb i (a, b)
forall (arra :: * -> * -> *) i a (arrb :: * -> * -> *) b.
arra i a -> arrb i b -> Arr2 arra arrb i (a, b)
Arr2 (marra i a -> marrb i b -> Arr2 marra marrb i (a, b))
-> m (marra i a) -> m (marrb i b -> Arr2 marra marrb i (a, b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (i, i) -> m (marra i a)
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
(i, i) -> m (a i e)
newArray_ (i, i)
b m (marrb i b -> Arr2 marra marrb i (a, b))
-> m (marrb i b) -> m (Arr2 marra marrb i (a, b))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (i, i) -> m (marrb i b)
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
(i, i) -> m (a i e)
newArray_ (i, i)
b
    unsafeRead :: Arr2 marra marrb i (a, b) -> Int -> m (a, b)
unsafeRead (Arr2 marra i a
xa marrb i b
ya) Int
i         = (,) (a -> b -> (a, b)) -> m a -> m (b -> (a, b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> marra i a -> Int -> m a
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> Int -> m e
unsafeRead marra i a
xa Int
i m (b -> (a, b)) -> m b -> m (a, b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> marrb i b -> Int -> m b
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> Int -> m e
unsafeRead marrb i b
ya Int
i
    unsafeWrite :: Arr2 marra marrb i (a, b) -> Int -> (a, b) -> m ()
unsafeWrite (Arr2 marra i a
xa marrb i b
ya) Int
i (a
x, b
y) = marra i a -> Int -> a -> m ()
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> Int -> e -> m ()
unsafeWrite marra i a
xa Int
i a
a
x m () -> m () -> m ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> marrb i b -> Int -> b -> m ()
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> Int -> e -> m ()
unsafeWrite marrb i b
ya Int
i b
b
y

type UArr2 = Arr2 UArray UArray
type UArr3 = Arr2 UArray UArr2
type UArr4 = Arr2 UArr2 UArr2

type STUArr2 s = Arr2 (STUArray s) (STUArray s)
type STUArr3 s = Arr2 (STUArray s) (STUArr2 s)
type STUArr4 s = Arr2 (STUArr2 s) (STUArr2 s)

type IOUArr2 = Arr2 IOUArray IOUArray
type IOUArr3 = Arr2 IOUArray IOUArr2
type IOUArr4 = Arr2 IOUArr2 IOUArr2

--------------------------------------------------------------------------------
-- For tests

instance NFData (arr i (Unboxed a)) => NFData (Arr arr i a) where
    rnf :: Arr arr i a -> ()
rnf = arr i (Unboxed a) -> ()
forall a. NFData a => a -> ()
rnf (arr i (Unboxed a) -> ())
-> (Arr arr i a -> arr i (Unboxed a)) -> Arr arr i a -> ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Arr arr i a -> arr i (Unboxed a)
forall (arr :: * -> * -> *) i a. Arr arr i a -> arr i (Unboxed a)
unArr

instance (NFData (arra i a), NFData (arrb i b)) => NFData (Arr2 arra arrb i (a, b)) where
    rnf :: Arr2 arra arrb i (a, b) -> ()
rnf (Arr2 arra i a
xa arrb i b
ya) = arra i a -> ()
forall a. NFData a => a -> ()
rnf arra i a
xa () -> () -> ()
`seq` arrb i b -> ()
forall a. NFData a => a -> ()
rnf arrb i b
ya