comfort-array-0.5.5: src/Data/Array/Comfort/Storable/Unchecked/Creator.hs
{-# LANGUAGE Rank2Types #-}
module Data.Array.Comfort.Storable.Unchecked.Creator where
import qualified Data.Array.Comfort.Shape.SubSize as SubSize
import qualified Data.Array.Comfort.Shape as Shape
import Data.Array.Comfort.Storable.Private (Array(Array))
import Foreign.Storable (Storable, )
import Foreign.Ptr (Ptr, )
import qualified Foreign.Marshal.Array.Guarded as Alloc
import qualified Control.Monad.Trans.Cont as MC
import Control.Monad.Primitive (PrimMonad, unsafeIOToPrim)
import Data.Biapplicative (Biapplicative(bipure, (<<*>>)))
import Data.Bifunctor (Bifunctor(bimap))
import Data.Tuple.HT (mapFst)
newtype Creator arr ptr = Creator (forall a. (ptr -> IO a) -> IO (arr, a))
liftIO :: IO ptr -> Creator () ptr
liftIO act = Creator $ \f -> fmap ((,) ()) $ f =<< act
liftContT :: (forall a. MC.ContT a IO ptr) -> Creator () ptr
liftContT act = Creator $ \f -> fmap ((,) ()) $ MC.runContT act f
instance Functor (Creator arr) where
fmap g (Creator act) = Creator $ \f -> act (f . g)
pair ::
Creator arr0 ptr0 -> Creator arr1 ptr1 ->
Creator (arr0,arr1) (ptr0,ptr1)
pair (Creator act0) (Creator act1) =
Creator $ \f ->
fmap (\(arr0,(arr1,a)) -> ((arr0,arr1),a)) $
act0 $ \ptr0 ->
act1 $ \ptr1 ->
f (ptr0, ptr1)
instance Bifunctor Creator where
bimap g h (Creator act) = Creator $ \f -> fmap (mapFst g) $ act (f . h)
instance Biapplicative Creator where
bipure a b = Creator $ \f -> fmap ((,) a) $ f b
creator0 <<*>> creator1 =
bimap (uncurry id) (uncurry id) $ pair creator0 creator1
unsafeRun :: (PrimMonad m) => Creator arr ptr -> (ptr -> IO ()) -> m arr
unsafeRun (Creator act) f = unsafeIOToPrim $ fmap (\(arr,()) -> arr) $ act f
unsafeRunWithResult ::
(PrimMonad m) => Creator arr ptr -> (ptr -> IO b) -> m (arr, b)
unsafeRunWithResult (Creator act) f = unsafeIOToPrim $ act f
{-# INLINE create #-}
create ::
(Shape.C sh, Storable a) =>
sh -> Creator (Array sh a) (Ptr a)
create sh = fmap snd $ createWithSize sh
{-# INLINE createWithSize #-}
createWithSize ::
(Shape.C sh, Storable a) =>
sh -> Creator (Array sh a) (Int, Ptr a)
createWithSize sh =
let size = Shape.size sh
in Creator $ \f ->
fmap (mapFst (Array sh)) $ Alloc.create size $ curry f size
{-# INLINE createWithSizes #-}
createWithSizes ::
(Shape.C sh, Storable a) =>
SubSize.T sh nsize -> sh -> Creator (Array sh a) (nsize, Ptr a)
createWithSizes (SubSize.Cons subSize) sh =
let (size, subSizes) = subSize sh
in Creator $ \f ->
fmap (mapFst (Array sh)) $ Alloc.create size $ curry f subSizes