loops-0.1.0.1: src/Control/Monad/Loop/ForEach.hs
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
module Control.Monad.Loop.ForEach where
import Control.Monad (liftM)
import Control.Monad.Primitive (PrimMonad, PrimState)
import Control.Monad.Trans.Class (lift)
-- Import the vector package qualified to write the ForEach instances
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as MV
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Generic.Mutable as MG
import qualified Data.Vector.Primitive as P
import qualified Data.Vector.Primitive.Mutable as MP
import qualified Data.Vector.Storable as S
import qualified Data.Vector.Storable.Mutable as MS
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Unboxed.Mutable as MU
import Control.Monad.Loop.Internal
-- | Class of containers that can be iterated over. The class is
-- parameterized over a base monad where the values of the container can be
-- read to allow iterating over mutable structures. The associated type
-- families parameterize the value and index types of the container,
-- allowing the class to be instantiated for container types (unboxed or
-- storable vectors, for example) which do not admit all types as values.
class ForEach m c where
type ForEachValue c
type ForEachIx c
-- | Iterate over the values in the container.
forEach :: c -> m (ForEachValue c)
-- | Iterate over the indices and the value at each index.
iforEach :: c -> m (ForEachIx c, ForEachValue c)
instance (Monad m) => ForEach (LoopT m) [a] where
type ForEachValue [a] = a
type ForEachIx [a] = Int
forEach as = liftM head $ for as (not . null) tail
{-# INLINE forEach #-}
iforEach = forEach . zip [0..]
{-# INLINE iforEach #-}
instance (Monad m) => ForEach (LoopT m) (V.Vector a) where
type ForEachValue (V.Vector a) = a
type ForEachIx (V.Vector a) = Int
forEach = forEachVector
iforEach = iforEachVector
{-# INLINE forEach #-}
{-# INLINE iforEach #-}
instance (Monad m, U.Unbox a) => ForEach (LoopT m) (U.Vector a) where
type ForEachValue (U.Vector a) = a
type ForEachIx (U.Vector a) = Int
forEach = forEachVector
iforEach = iforEachVector
{-# INLINE forEach #-}
{-# INLINE iforEach #-}
instance (Monad m, P.Prim a) => ForEach (LoopT m) (P.Vector a) where
type ForEachValue (P.Vector a) = a
type ForEachIx (P.Vector a) = Int
forEach = forEachVector
iforEach = iforEachVector
{-# INLINE forEach #-}
{-# INLINE iforEach #-}
instance (Monad m, S.Storable a) => ForEach (LoopT m) (S.Vector a) where
type ForEachValue (S.Vector a) = a
type ForEachIx (S.Vector a) = Int
forEach = forEachVector
iforEach = iforEachVector
{-# INLINE forEach #-}
{-# INLINE iforEach #-}
forEachVector :: (Monad m, G.Vector v a) => v a -> LoopT m a
{-# INLINE forEachVector #-}
forEachVector = liftM snd . iforEachVector
iforEachVector :: (Monad m, G.Vector v a) => v a -> LoopT m (Int, a)
{-# INLINE iforEachVector #-}
iforEachVector v = do
let len = G.length v
i <- for 0 (< len) (+ 1)
x <- G.unsafeIndexM v i
return (i, x)
instance (PrimMonad m, PrimState m ~ s) => ForEach (LoopT m) (MV.MVector s a) where
type ForEachValue (MV.MVector s a) = a
type ForEachIx (MV.MVector s a) = Int
forEach = forEachMVector
iforEach = iforEachMVector
{-# INLINE forEach #-}
{-# INLINE iforEach #-}
instance (PrimMonad m, U.Unbox a, PrimState m ~ s) => ForEach (LoopT m) (MU.MVector s a) where
type ForEachValue (MU.MVector s a) = a
type ForEachIx (MU.MVector s a) = Int
forEach = forEachMVector
iforEach = iforEachMVector
{-# INLINE forEach #-}
{-# INLINE iforEach #-}
instance (PrimMonad m, P.Prim a, PrimState m ~ s) => ForEach (LoopT m) (MP.MVector s a) where
type ForEachValue (MP.MVector s a) = a
type ForEachIx (MP.MVector s a) = Int
forEach = forEachMVector
iforEach = iforEachMVector
{-# INLINE forEach #-}
{-# INLINE iforEach #-}
instance (S.Storable a, PrimMonad m, PrimState m ~ s) => ForEach (LoopT m) (MS.MVector s a) where
type ForEachValue (MS.MVector s a) = a
type ForEachIx (MS.MVector s a) = Int
forEach = forEachMVector
iforEach = iforEachMVector
{-# INLINE forEach #-}
{-# INLINE iforEach #-}
forEachMVector :: (PrimMonad m, MG.MVector v a) => v (PrimState m) a -> LoopT m a
{-# INLINE forEachMVector #-}
forEachMVector = liftM snd . iforEachMVector
iforEachMVector :: (PrimMonad m, MG.MVector v a) => v (PrimState m) a -> LoopT m (Int, a)
{-# INLINE iforEachMVector #-}
iforEachMVector v = do
let len = MG.length v
i <- for 0 (< len) (+ 1)
x <- lift $ MG.unsafeRead v i
return (i, x)