    -- |
    -- Module      : Basement.Sized.Block
    -- License     : BSD-style
    -- Maintainer  : Haskell Foundation
    --
    -- A Nat-sized version of Block
    {-# LANGUAGE AllowAmbiguousTypes        #-}
    {-# LANGUAGE CPP                        #-}
    {-# LANGUAGE ConstraintKinds            #-}
    {-# LANGUAGE DataKinds                  #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE ScopedTypeVariables        #-}
    {-# LANGUAGE TypeApplications           #-}
    {-# LANGUAGE TypeOperators              #-}
    #if __GLASGOW_HASKELL__ >= 806
    {-# LANGUAGE NoStarIsType               #-}
    #endif

    module Basement.Sized.Block
        ( BlockN
        , MutableBlockN
        , length
        , lengthBytes
        , toBlockN
        , toBlock
        , new
        , newPinned
        , singleton
        , replicate
        , thaw
        , freeze
        , index
        , indexStatic
        , map
        , foldl'
        , foldr
        , cons
        , snoc
        , elem
        , sub
        , uncons
        , unsnoc
        , splitAt
        , all
        , any
        , find
        , reverse
        , sortBy
        , intersperse
        , withPtr
        , withMutablePtr
        , withMutablePtrHint
        , cast
        , mutableCast
        ) where

    import           Data.Proxy (Proxy(..))
    import           Basement.Compat.Base
    import           Basement.Numerical.Additive (scale)
    import           Basement.Block (Block, MutableBlock(..), unsafeIndex)
    import qualified Basement.Block as B
    import qualified Basement.Block.Base as B
    import           Basement.Monad (PrimMonad, PrimState)
    import           Basement.Nat
    import           Basement.Types.OffsetSize
    import           Basement.NormalForm
    import           Basement.PrimType (PrimType, PrimSize, primSizeInBytes)

    -- | Sized version of 'Block'
    --
    newtype BlockN (n :: Nat) a = BlockN { forall (n :: Nat) a. BlockN n a -> Block a
    unBlock :: Block a }
      deriving (BlockN n a -> ()
    (BlockN n a -> ()) -> NormalForm (BlockN n a)
    forall (n :: Nat) a. BlockN n a -> ()
    forall a. (a -> ()) -> NormalForm a
    $ctoNormalForm :: forall (n :: Nat) a. BlockN n a -> ()
    toNormalForm :: BlockN n a -> ()
    NormalForm, BlockN n a -> BlockN n a -> Bool
    (BlockN n a -> BlockN n a -> Bool)
    -> (BlockN n a -> BlockN n a -> Bool) -> Eq (BlockN n a)
    forall (n :: Nat) a. PrimType a => BlockN n a -> BlockN n a -> Bool
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: forall (n :: Nat) a. PrimType a => BlockN n a -> BlockN n a -> Bool
    == :: BlockN n a -> BlockN n a -> Bool
    $c/= :: forall (n :: Nat) a. PrimType a => BlockN n a -> BlockN n a -> Bool
    /= :: BlockN n a -> BlockN n a -> Bool
    Eq, Int -> BlockN n a -> ShowS
    [BlockN n a] -> ShowS
    BlockN n a -> String
    (Int -> BlockN n a -> ShowS)
    -> (BlockN n a -> String)
    -> ([BlockN n a] -> ShowS)
    -> Show (BlockN n a)
    forall (n :: Nat) a.
    (PrimType a, Show a) =>
    Int -> BlockN n a -> ShowS
    forall (n :: Nat) a. (PrimType a, Show a) => [BlockN n a] -> ShowS
    forall (n :: Nat) a. (PrimType a, Show a) => BlockN n a -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall (n :: Nat) a.
    (PrimType a, Show a) =>
    Int -> BlockN n a -> ShowS
    showsPrec :: Int -> BlockN n a -> ShowS
    $cshow :: forall (n :: Nat) a. (PrimType a, Show a) => BlockN n a -> String
    show :: BlockN n a -> String
    $cshowList :: forall (n :: Nat) a. (PrimType a, Show a) => [BlockN n a] -> ShowS
    showList :: [BlockN n a] -> ShowS
    Show, Typeable (BlockN n a)
    Typeable (BlockN n a)
    -> (forall (c :: Type -> Type).
        (forall d b. Data d => c (d -> b) -> d -> c b)
        -> (forall g. g -> c g) -> BlockN n a -> c (BlockN n a))
    -> (forall (c :: Type -> Type).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c (BlockN n a))
    -> (BlockN n a -> Constr)
    -> (BlockN n a -> DataType)
    -> (forall (t :: Type -> Type) (c :: Type -> Type).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c (BlockN n a)))
    -> (forall (t :: Type -> Type -> Type) (c :: Type -> Type).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e))
        -> Maybe (c (BlockN n a)))
    -> ((forall b. Data b => b -> b) -> BlockN n a -> BlockN n a)
    -> (forall r r'.
        (r -> r' -> r)
        -> r -> (forall d. Data d => d -> r') -> BlockN n a -> r)
    -> (forall r r'.
        (r' -> r -> r)
        -> r -> (forall d. Data d => d -> r') -> BlockN n a -> r)
    -> (forall u. (forall d. Data d => d -> u) -> BlockN n a -> [u])
    -> (forall u.
        Int -> (forall d. Data d => d -> u) -> BlockN n a -> u)
    -> (forall (m :: Type -> Type).
        Monad m =>
        (forall d. Data d => d -> m d) -> BlockN n a -> m (BlockN n a))
    -> (forall (m :: Type -> Type).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> BlockN n a -> m (BlockN n a))
    -> (forall (m :: Type -> Type).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> BlockN n a -> m (BlockN n a))
    -> Data (BlockN n a)
    BlockN n a -> Constr
    BlockN n a -> DataType
    (forall b. Data b => b -> b) -> BlockN n a -> BlockN n a
    forall {n :: Nat} {a}.
    (KnownNat n, Data a) =>
    Typeable (BlockN n a)
    forall (n :: Nat) a. (KnownNat n, Data a) => BlockN n a -> Constr
    forall (n :: Nat) a. (KnownNat n, Data a) => BlockN n a -> DataType
    forall (n :: Nat) a.
    (KnownNat n, Data a) =>
    (forall b. Data b => b -> b) -> BlockN n a -> BlockN n a
    forall (n :: Nat) a u.
    (KnownNat n, Data a) =>
    Int -> (forall d. Data d => d -> u) -> BlockN n a -> u
    forall (n :: Nat) a u.
    (KnownNat n, Data a) =>
    (forall d. Data d => d -> u) -> BlockN n a -> [u]
    forall (n :: Nat) a r r'.
    (KnownNat n, Data a) =>
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> BlockN n a -> r
    forall (n :: Nat) a r r'.
    (KnownNat n, Data a) =>
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> BlockN n a -> r
    forall (n :: Nat) a (m :: Type -> Type).
    (KnownNat n, Data a, Monad m) =>
    (forall d. Data d => d -> m d) -> BlockN n a -> m (BlockN n a)
    forall (n :: Nat) a (m :: Type -> Type).
    (KnownNat n, Data a, MonadPlus m) =>
    (forall d. Data d => d -> m d) -> BlockN n a -> m (BlockN n a)
    forall (n :: Nat) a (c :: Type -> Type).
    (KnownNat n, Data a) =>
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (BlockN n a)
    forall (n :: Nat) a (c :: Type -> Type).
    (KnownNat n, Data a) =>
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> BlockN n a -> c (BlockN n a)
    forall (n :: Nat) a (t :: Type -> Type) (c :: Type -> Type).
    (KnownNat n, Data a, Typeable t) =>
    (forall d. Data d => c (t d)) -> Maybe (c (BlockN n a))
    forall (n :: Nat) a (t :: Type -> Type -> Type)
           (c :: Type -> Type).
    (KnownNat n, Data a, Typeable t) =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (BlockN n a))
    forall a.
    Typeable a
    -> (forall (c :: Type -> Type).
        (forall d b. Data d => c (d -> b) -> d -> c b)
        -> (forall g. g -> c g) -> a -> c a)
    -> (forall (c :: Type -> Type).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c a)
    -> (a -> Constr)
    -> (a -> DataType)
    -> (forall (t :: Type -> Type) (c :: Type -> Type).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c a))
    -> (forall (t :: Type -> Type -> Type) (c :: Type -> Type).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
    -> ((forall b. Data b => b -> b) -> a -> a)
    -> (forall r r'.
        (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall r r'.
        (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall u. (forall d. Data d => d -> u) -> a -> [u])
    -> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
    -> (forall (m :: Type -> Type).
        Monad m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: Type -> Type).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: Type -> Type).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> Data a
    forall u. Int -> (forall d. Data d => d -> u) -> BlockN n a -> u
    forall u. (forall d. Data d => d -> u) -> BlockN n a -> [u]
    forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> BlockN n a -> r
    forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> BlockN n a -> r
    forall (m :: Type -> Type).
    Monad m =>
    (forall d. Data d => d -> m d) -> BlockN n a -> m (BlockN n a)
    forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> BlockN n a -> m (BlockN n a)
    forall (c :: Type -> Type).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (BlockN n a)
    forall (c :: Type -> Type).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> BlockN n a -> c (BlockN n a)
    forall (t :: Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (BlockN n a))
    forall (t :: Type -> Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (BlockN n a))
    $cgfoldl :: forall (n :: Nat) a (c :: Type -> Type).
    (KnownNat n, Data a) =>
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> BlockN n a -> c (BlockN n a)
    gfoldl :: forall (c :: Type -> Type).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> BlockN n a -> c (BlockN n a)
    $cgunfold :: forall (n :: Nat) a (c :: Type -> Type).
    (KnownNat n, Data a) =>
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (BlockN n a)
    gunfold :: forall (c :: Type -> Type).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (BlockN n a)
    $ctoConstr :: forall (n :: Nat) a. (KnownNat n, Data a) => BlockN n a -> Constr
    toConstr :: BlockN n a -> Constr
    $cdataTypeOf :: forall (n :: Nat) a. (KnownNat n, Data a) => BlockN n a -> DataType
    dataTypeOf :: BlockN n a -> DataType
    $cdataCast1 :: forall (n :: Nat) a (t :: Type -> Type) (c :: Type -> Type).
    (KnownNat n, Data a, Typeable t) =>
    (forall d. Data d => c (t d)) -> Maybe (c (BlockN n a))
    dataCast1 :: forall (t :: Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c (BlockN n a))
    $cdataCast2 :: forall (n :: Nat) a (t :: Type -> Type -> Type)
           (c :: Type -> Type).
    (KnownNat n, Data a, Typeable t) =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (BlockN n a))
    dataCast2 :: forall (t :: Type -> Type -> Type) (c :: Type -> Type).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c (BlockN n a))
    $cgmapT :: forall (n :: Nat) a.
    (KnownNat n, Data a) =>
    (forall b. Data b => b -> b) -> BlockN n a -> BlockN n a
    gmapT :: (forall b. Data b => b -> b) -> BlockN n a -> BlockN n a
    $cgmapQl :: forall (n :: Nat) a r r'.
    (KnownNat n, Data a) =>
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> BlockN n a -> r
    gmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> BlockN n a -> r
    $cgmapQr :: forall (n :: Nat) a r r'.
    (KnownNat n, Data a) =>
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> BlockN n a -> r
    gmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> BlockN n a -> r
    $cgmapQ :: forall (n :: Nat) a u.
    (KnownNat n, Data a) =>
    (forall d. Data d => d -> u) -> BlockN n a -> [u]
    gmapQ :: forall u. (forall d. Data d => d -> u) -> BlockN n a -> [u]
    $cgmapQi :: forall (n :: Nat) a u.
    (KnownNat n, Data a) =>
    Int -> (forall d. Data d => d -> u) -> BlockN n a -> u
    gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> BlockN n a -> u
    $cgmapM :: forall (n :: Nat) a (m :: Type -> Type).
    (KnownNat n, Data a, Monad m) =>
    (forall d. Data d => d -> m d) -> BlockN n a -> m (BlockN n a)
    gmapM :: forall (m :: Type -> Type).
    Monad m =>
    (forall d. Data d => d -> m d) -> BlockN n a -> m (BlockN n a)
    $cgmapMp :: forall (n :: Nat) a (m :: Type -> Type).
    (KnownNat n, Data a, MonadPlus m) =>
    (forall d. Data d => d -> m d) -> BlockN n a -> m (BlockN n a)
    gmapMp :: forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> BlockN n a -> m (BlockN n a)
    $cgmapMo :: forall (n :: Nat) a (m :: Type -> Type).
    (KnownNat n, Data a, MonadPlus m) =>
    (forall d. Data d => d -> m d) -> BlockN n a -> m (BlockN n a)
    gmapMo :: forall (m :: Type -> Type).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> BlockN n a -> m (BlockN n a)
    Data, Eq (BlockN n a)
    Eq (BlockN n a)
    -> (BlockN n a -> BlockN n a -> Ordering)
    -> (BlockN n a -> BlockN n a -> Bool)
    -> (BlockN n a -> BlockN n a -> Bool)
    -> (BlockN n a -> BlockN n a -> Bool)
    -> (BlockN n a -> BlockN n a -> Bool)
    -> (BlockN n a -> BlockN n a -> BlockN n a)
    -> (BlockN n a -> BlockN n a -> BlockN n a)
    -> Ord (BlockN n a)
    BlockN n a -> BlockN n a -> Bool
    BlockN n a -> BlockN n a -> Ordering
    BlockN n a -> BlockN n a -> BlockN n a
    forall {n :: Nat} {a}. (PrimType a, Ord a) => Eq (BlockN n a)
    forall (n :: Nat) a.
    (PrimType a, Ord a) =>
    BlockN n a -> BlockN n a -> Bool
    forall (n :: Nat) a.
    (PrimType a, Ord a) =>
    BlockN n a -> BlockN n a -> Ordering
    forall (n :: Nat) a.
    (PrimType a, Ord a) =>
    BlockN n a -> BlockN n a -> BlockN n a
    forall a.
    Eq a
    -> (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: forall (n :: Nat) a.
    (PrimType a, Ord a) =>
    BlockN n a -> BlockN n a -> Ordering
    compare :: BlockN n a -> BlockN n a -> Ordering
    $c< :: forall (n :: Nat) a.
    (PrimType a, Ord a) =>
    BlockN n a -> BlockN n a -> Bool
    < :: BlockN n a -> BlockN n a -> Bool
    $c<= :: forall (n :: Nat) a.
    (PrimType a, Ord a) =>
    BlockN n a -> BlockN n a -> Bool
    <= :: BlockN n a -> BlockN n a -> Bool
    $c> :: forall (n :: Nat) a.
    (PrimType a, Ord a) =>
    BlockN n a -> BlockN n a -> Bool
    > :: BlockN n a -> BlockN n a -> Bool
    $c>= :: forall (n :: Nat) a.
    (PrimType a, Ord a) =>
    BlockN n a -> BlockN n a -> Bool
    >= :: BlockN n a -> BlockN n a -> Bool
    $cmax :: forall (n :: Nat) a.
    (PrimType a, Ord a) =>
    BlockN n a -> BlockN n a -> BlockN n a
    max :: BlockN n a -> BlockN n a -> BlockN n a
    $cmin :: forall (n :: Nat) a.
    (PrimType a, Ord a) =>
    BlockN n a -> BlockN n a -> BlockN n a
    min :: BlockN n a -> BlockN n a -> BlockN n a
    Ord)

    newtype MutableBlockN (n :: Nat) ty st = MutableBlockN { forall (n :: Nat) ty st.
    MutableBlockN n ty st -> MutableBlock ty st
    unMBlock :: MutableBlock ty st }

    toBlockN :: forall n ty . (PrimType ty, KnownNat n, Countable ty n) => Block ty -> Maybe (BlockN n ty)
    toBlockN :: forall (n :: Nat) ty.
    (PrimType ty, KnownNat n, Countable ty n) =>
    Block ty -> Maybe (BlockN n ty)
    toBlockN Block ty
    b
        | CountOf ty
    expected CountOf ty -> CountOf ty -> Bool
    forall a. Eq a => a -> a -> Bool
    == Block ty -> CountOf ty
    forall ty. PrimType ty => Block ty -> CountOf ty
    B.length Block ty
    b = BlockN n ty -> Maybe (BlockN n ty)
    forall a. a -> Maybe a
    Just (Block ty -> BlockN n ty
    forall (n :: Nat) a. Block a -> BlockN n a
    BlockN Block ty
    b)
        | Bool
    otherwise = Maybe (BlockN n ty)
    forall a. Maybe a
    Nothing
      where
        expected :: CountOf ty
    expected = forall (n :: Nat) ty. (KnownNat n, Countable ty n) => CountOf ty
    toCount @n

    length :: forall n ty
            . (KnownNat n, Countable ty n)
           => BlockN n ty
           -> CountOf ty
    length :: forall (n :: Nat) ty.
    (KnownNat n, Countable ty n) =>
    BlockN n ty -> CountOf ty
    length BlockN n ty
    _ = forall (n :: Nat) ty. (KnownNat n, Countable ty n) => CountOf ty
    toCount @n

    lengthBytes :: forall n ty
                 . PrimType ty
                => BlockN n ty
                -> CountOf Word8
    lengthBytes :: forall (n :: Nat) ty. PrimType ty => BlockN n ty -> CountOf Word8
    lengthBytes = Block ty -> CountOf Word8
    forall ty. Block ty -> CountOf Word8
    B.lengthBytes (Block ty -> CountOf Word8)
    -> (BlockN n ty -> Block ty) -> BlockN n ty -> CountOf Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock

    toBlock :: BlockN n ty -> Block ty
    toBlock :: forall (n :: Nat) a. BlockN n a -> Block a
    toBlock = BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock

    cast :: forall n m a b
          . ( PrimType a, PrimType b
            , KnownNat n, KnownNat m
            , ((PrimSize b) * m) ~ ((PrimSize a) * n)
            )
          => BlockN n a
          -> BlockN m b
    cast :: forall (n :: Nat) (m :: Nat) a b.
    (PrimType a, PrimType b, KnownNat n, KnownNat m,
     (PrimSize b * m) ~ (PrimSize a * n)) =>
    BlockN n a -> BlockN m b
    cast (BlockN Block a
    b) = Block b -> BlockN m b
    forall (n :: Nat) a. Block a -> BlockN n a
    BlockN (Block a -> Block b
    forall b a. PrimType b => Block a -> Block b
    B.unsafeCast Block a
    b)

    mutableCast :: forall n m a b st
                 . ( PrimType a, PrimType b
                 , KnownNat n, KnownNat m
                 , ((PrimSize b) * m) ~ ((PrimSize a) * n)
                 )
                => MutableBlockN n a st
                -> MutableBlockN m b st
    mutableCast :: forall (n :: Nat) (m :: Nat) a b st.
    (PrimType a, PrimType b, KnownNat n, KnownNat m,
     (PrimSize b * m) ~ (PrimSize a * n)) =>
    MutableBlockN n a st -> MutableBlockN m b st
    mutableCast (MutableBlockN MutableBlock a st
    b) = MutableBlock b st -> MutableBlockN m b st
    forall (n :: Nat) ty st.
    MutableBlock ty st -> MutableBlockN n ty st
    MutableBlockN (MutableBlock a st -> MutableBlock b st
    forall t1 t2 st.
    (PrimType t1, PrimType t2) =>
    MutableBlock t1 st -> MutableBlock t2 st
    B.unsafeRecast MutableBlock a st
    b)

    -- | Create a new unpinned mutable block of a specific N size of 'ty' elements
    --
    -- If the size exceeds a GHC-defined threshold, then the memory will be
    -- pinned. To be certain about pinning status with small size, use 'newPinned'
    new :: forall n ty prim
         . (PrimType ty, KnownNat n, Countable ty n, PrimMonad prim)
        => prim (MutableBlockN n ty (PrimState prim))
    new :: forall (n :: Nat) ty (prim :: Type -> Type).
    (PrimType ty, KnownNat n, Countable ty n, PrimMonad prim) =>
    prim (MutableBlockN n ty (PrimState prim))
    new = MutableBlock ty (PrimState prim)
    -> MutableBlockN n ty (PrimState prim)
    forall (n :: Nat) ty st.
    MutableBlock ty st -> MutableBlockN n ty st
    MutableBlockN (MutableBlock ty (PrimState prim)
     -> MutableBlockN n ty (PrimState prim))
    -> prim (MutableBlock ty (PrimState prim))
    -> prim (MutableBlockN n ty (PrimState prim))
    forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
    <$> CountOf ty -> prim (MutableBlock ty (PrimState prim))
    forall (prim :: Type -> Type) ty.
    (PrimMonad prim, PrimType ty) =>
    CountOf ty -> prim (MutableBlock ty (PrimState prim))
    B.new (forall (n :: Nat) ty. (KnownNat n, Countable ty n) => CountOf ty
    toCount @n)

    -- | Create a new pinned mutable block of a specific N size of 'ty' elements
    newPinned :: forall n ty prim
               . (PrimType ty, KnownNat n, Countable ty n, PrimMonad prim)
              => prim (MutableBlockN n ty (PrimState prim))
    newPinned :: forall (n :: Nat) ty (prim :: Type -> Type).
    (PrimType ty, KnownNat n, Countable ty n, PrimMonad prim) =>
    prim (MutableBlockN n ty (PrimState prim))
    newPinned = MutableBlock ty (PrimState prim)
    -> MutableBlockN n ty (PrimState prim)
    forall (n :: Nat) ty st.
    MutableBlock ty st -> MutableBlockN n ty st
    MutableBlockN (MutableBlock ty (PrimState prim)
     -> MutableBlockN n ty (PrimState prim))
    -> prim (MutableBlock ty (PrimState prim))
    -> prim (MutableBlockN n ty (PrimState prim))
    forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
    <$> CountOf ty -> prim (MutableBlock ty (PrimState prim))
    forall (prim :: Type -> Type) ty.
    (PrimMonad prim, PrimType ty) =>
    CountOf ty -> prim (MutableBlock ty (PrimState prim))
    B.newPinned (forall (n :: Nat) ty. (KnownNat n, Countable ty n) => CountOf ty
    toCount @n)

    singleton :: PrimType ty => ty -> BlockN 1 ty
    singleton :: forall ty. PrimType ty => ty -> BlockN 1 ty
    singleton ty
    a = Block ty -> BlockN 1 ty
    forall (n :: Nat) a. Block a -> BlockN n a
    BlockN (ty -> Block ty
    forall ty. PrimType ty => ty -> Block ty
    B.singleton ty
    a)

    replicate :: forall n ty . (KnownNat n, Countable ty n, PrimType ty) => ty -> BlockN n ty
    replicate :: forall (n :: Nat) ty.
    (KnownNat n, Countable ty n, PrimType ty) =>
    ty -> BlockN n ty
    replicate ty
    a = Block ty -> BlockN n ty
    forall (n :: Nat) a. Block a -> BlockN n a
    BlockN (CountOf ty -> ty -> Block ty
    forall ty. PrimType ty => CountOf ty -> ty -> Block ty
    B.replicate (forall (n :: Nat) ty. (KnownNat n, Countable ty n) => CountOf ty
    toCount @n) ty
    a)

    thaw :: (KnownNat n, PrimMonad prim, PrimType ty) => BlockN n ty -> prim (MutableBlockN n ty (PrimState prim))
    thaw :: forall (n :: Nat) (prim :: Type -> Type) ty.
    (KnownNat n, PrimMonad prim, PrimType ty) =>
    BlockN n ty -> prim (MutableBlockN n ty (PrimState prim))
    thaw BlockN n ty
    b = MutableBlock ty (PrimState prim)
    -> MutableBlockN n ty (PrimState prim)
    forall (n :: Nat) ty st.
    MutableBlock ty st -> MutableBlockN n ty st
    MutableBlockN (MutableBlock ty (PrimState prim)
     -> MutableBlockN n ty (PrimState prim))
    -> prim (MutableBlock ty (PrimState prim))
    -> prim (MutableBlockN n ty (PrimState prim))
    forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
    <$> Block ty -> prim (MutableBlock ty (PrimState prim))
    forall (prim :: Type -> Type) ty.
    (PrimMonad prim, PrimType ty) =>
    Block ty -> prim (MutableBlock ty (PrimState prim))
    B.thaw (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b)

    freeze ::  (PrimMonad prim, PrimType ty, Countable ty n) => MutableBlockN n ty (PrimState prim) -> prim (BlockN n ty)
    freeze :: forall (prim :: Type -> Type) ty (n :: Nat).
    (PrimMonad prim, PrimType ty, Countable ty n) =>
    MutableBlockN n ty (PrimState prim) -> prim (BlockN n ty)
    freeze MutableBlockN n ty (PrimState prim)
    b = Block ty -> BlockN n ty
    forall (n :: Nat) a. Block a -> BlockN n a
    BlockN (Block ty -> BlockN n ty) -> prim (Block ty) -> prim (BlockN n ty)
    forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
    <$> MutableBlock ty (PrimState prim) -> prim (Block ty)
    forall ty (prim :: Type -> Type).
    (PrimType ty, PrimMonad prim) =>
    MutableBlock ty (PrimState prim) -> prim (Block ty)
    B.freeze (MutableBlockN n ty (PrimState prim)
    -> MutableBlock ty (PrimState prim)
    forall (n :: Nat) ty st.
    MutableBlockN n ty st -> MutableBlock ty st
    unMBlock MutableBlockN n ty (PrimState prim)
    b)

    indexStatic :: forall i n ty . (KnownNat i, CmpNat i n ~ 'LT, PrimType ty, Offsetable ty i) => BlockN n ty -> ty
    indexStatic :: forall (i :: Nat) (n :: Nat) ty.
    (KnownNat i, CmpNat i n ~ 'LT, PrimType ty, Offsetable ty i) =>
    BlockN n ty -> ty
    indexStatic BlockN n ty
    b = Block ty -> Offset ty -> ty
    forall ty. PrimType ty => Block ty -> Offset ty -> ty
    unsafeIndex (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b) (forall (n :: Nat) ty. (KnownNat n, Offsetable ty n) => Offset ty
    toOffset @i)

    index :: forall i n ty . PrimType ty => BlockN n ty -> Offset ty -> ty
    index :: forall i (n :: Nat) ty.
    PrimType ty =>
    BlockN n ty -> Offset ty -> ty
    index BlockN n ty
    b Offset ty
    ofs = Block ty -> Offset ty -> ty
    forall ty. PrimType ty => Block ty -> Offset ty -> ty
    B.index (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b) Offset ty
    ofs

    map :: (PrimType a, PrimType b) => (a -> b) -> BlockN n a -> BlockN n b
    map :: forall a b (n :: Nat).
    (PrimType a, PrimType b) =>
    (a -> b) -> BlockN n a -> BlockN n b
    map a -> b
    f BlockN n a
    b = Block b -> BlockN n b
    forall (n :: Nat) a. Block a -> BlockN n a
    BlockN ((a -> b) -> Block a -> Block b
    forall a b.
    (PrimType a, PrimType b) =>
    (a -> b) -> Block a -> Block b
    B.map a -> b
    f (BlockN n a -> Block a
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n a
    b))

    foldl' :: PrimType ty => (a -> ty -> a) -> a -> BlockN n ty -> a
    foldl' :: forall ty a (n :: Nat).
    PrimType ty =>
    (a -> ty -> a) -> a -> BlockN n ty -> a
    foldl' a -> ty -> a
    f a
    acc BlockN n ty
    b = (a -> ty -> a) -> a -> Block ty -> a
    forall ty a. PrimType ty => (a -> ty -> a) -> a -> Block ty -> a
    B.foldl' a -> ty -> a
    f a
    acc (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b)

    foldr :: PrimType ty => (ty -> a -> a) -> a -> BlockN n ty -> a
    foldr :: forall ty a (n :: Nat).
    PrimType ty =>
    (ty -> a -> a) -> a -> BlockN n ty -> a
    foldr ty -> a -> a
    f a
    acc BlockN n ty
    b = (ty -> a -> a) -> a -> Block ty -> a
    forall ty a. PrimType ty => (ty -> a -> a) -> a -> Block ty -> a
    B.foldr ty -> a -> a
    f a
    acc (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b)

    cons :: PrimType ty => ty -> BlockN n ty -> BlockN (n+1) ty
    cons :: forall ty (n :: Nat).
    PrimType ty =>
    ty -> BlockN n ty -> BlockN (n + 1) ty
    cons ty
    e = Block ty -> BlockN (n + 1) ty
    forall (n :: Nat) a. Block a -> BlockN n a
    BlockN (Block ty -> BlockN (n + 1) ty)
    -> (BlockN n ty -> Block ty) -> BlockN n ty -> BlockN (n + 1) ty
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . ty -> Block ty -> Block ty
    forall ty. PrimType ty => ty -> Block ty -> Block ty
    B.cons ty
    e (Block ty -> Block ty)
    -> (BlockN n ty -> Block ty) -> BlockN n ty -> Block ty
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock

    snoc :: PrimType ty => BlockN n ty -> ty -> BlockN (n+1) ty
    snoc :: forall ty (n :: Nat).
    PrimType ty =>
    BlockN n ty -> ty -> BlockN (n + 1) ty
    snoc BlockN n ty
    b = Block ty -> BlockN (n + 1) ty
    forall (n :: Nat) a. Block a -> BlockN n a
    BlockN (Block ty -> BlockN (n + 1) ty)
    -> (ty -> Block ty) -> ty -> BlockN (n + 1) ty
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . Block ty -> ty -> Block ty
    forall ty. PrimType ty => Block ty -> ty -> Block ty
    B.snoc (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b)

    sub :: forall i j n ty
         . ( (i <=? n) ~ 'True
           , (j <=? n) ~ 'True
           , (i <=? j) ~ 'True
           , PrimType ty
           , KnownNat i
           , KnownNat j
           , Offsetable ty i
           , Offsetable ty j )
        => BlockN n ty
        -> BlockN (j-i) ty
    sub :: forall (i :: Nat) (j :: Nat) (n :: Nat) ty.
    ((i <=? n) ~ 'True, (j <=? n) ~ 'True, (i <=? j) ~ 'True,
     PrimType ty, KnownNat i, KnownNat j, Offsetable ty i,
     Offsetable ty j) =>
    BlockN n ty -> BlockN (j - i) ty
    sub BlockN n ty
    block = Block ty -> BlockN (j - i) ty
    forall (n :: Nat) a. Block a -> BlockN n a
    BlockN (Block ty -> Offset ty -> Offset ty -> Block ty
    forall ty.
    PrimType ty =>
    Block ty -> Offset ty -> Offset ty -> Block ty
    B.sub (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    block) (forall (n :: Nat) ty. (KnownNat n, Offsetable ty n) => Offset ty
    toOffset @i) (forall (n :: Nat) ty. (KnownNat n, Offsetable ty n) => Offset ty
    toOffset @j))

    uncons :: forall n ty . (CmpNat 0 n ~ 'LT, PrimType ty, KnownNat n, Offsetable ty n)
           => BlockN n ty
           -> (ty, BlockN (n-1) ty)
    uncons :: forall (n :: Nat) ty.
    (CmpNat 0 n ~ 'LT, PrimType ty, KnownNat n, Offsetable ty n) =>
    BlockN n ty -> (ty, BlockN (n - 1) ty)
    uncons BlockN n ty
    b = (forall (i :: Nat) (n :: Nat) ty.
    (KnownNat i, CmpNat i n ~ 'LT, PrimType ty, Offsetable ty i) =>
    BlockN n ty -> ty
    indexStatic @0 BlockN n ty
    b, Block ty -> BlockN (n - 1) ty
    forall (n :: Nat) a. Block a -> BlockN n a
    BlockN (Block ty -> Offset ty -> Offset ty -> Block ty
    forall ty.
    PrimType ty =>
    Block ty -> Offset ty -> Offset ty -> Block ty
    B.sub (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b) Offset ty
    1 (forall (n :: Nat) ty. (KnownNat n, Offsetable ty n) => Offset ty
    toOffset @n)))

    unsnoc :: forall n ty . (CmpNat 0 n ~ 'LT, KnownNat n, PrimType ty, Offsetable ty n)
           => BlockN n ty
           -> (BlockN (n-1) ty, ty)
    unsnoc :: forall (n :: Nat) ty.
    (CmpNat 0 n ~ 'LT, KnownNat n, PrimType ty, Offsetable ty n) =>
    BlockN n ty -> (BlockN (n - 1) ty, ty)
    unsnoc BlockN n ty
    b =
        ( Block ty -> BlockN (n - 1) ty
    forall (n :: Nat) a. Block a -> BlockN n a
    BlockN (Block ty -> Offset ty -> Offset ty -> Block ty
    forall ty.
    PrimType ty =>
    Block ty -> Offset ty -> Offset ty -> Block ty
    B.sub (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b) Offset ty
    0 (forall (n :: Nat) ty. (KnownNat n, Offsetable ty n) => Offset ty
    toOffset @n Offset ty -> Offset ty -> Offset ty
    forall a. Offset a -> Offset a -> Offset a
    `offsetSub` Offset ty
    1))
        , Block ty -> Offset ty -> ty
    forall ty. PrimType ty => Block ty -> Offset ty -> ty
    unsafeIndex (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b) (forall (n :: Nat) ty. (KnownNat n, Offsetable ty n) => Offset ty
    toOffset @n Offset ty -> Offset ty -> Offset ty
    forall a. Offset a -> Offset a -> Offset a
    `offsetSub` Offset ty
    1))

    splitAt :: forall i n ty . (CmpNat i n ~ 'LT, PrimType ty, KnownNat i, Countable ty i) => BlockN n ty -> (BlockN i ty, BlockN (n-i) ty)
    splitAt :: forall (i :: Nat) (n :: Nat) ty.
    (CmpNat i n ~ 'LT, PrimType ty, KnownNat i, Countable ty i) =>
    BlockN n ty -> (BlockN i ty, BlockN (n - i) ty)
    splitAt BlockN n ty
    b =
        let (Block ty
    left, Block ty
    right) = CountOf ty -> Block ty -> (Block ty, Block ty)
    forall ty.
    PrimType ty =>
    CountOf ty -> Block ty -> (Block ty, Block ty)
    B.splitAt (forall (n :: Nat) ty. (KnownNat n, Countable ty n) => CountOf ty
    toCount @i) (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b)
         in (Block ty -> BlockN i ty
    forall (n :: Nat) a. Block a -> BlockN n a
    BlockN Block ty
    left, Block ty -> BlockN (n - i) ty
    forall (n :: Nat) a. Block a -> BlockN n a
    BlockN Block ty
    right)

    elem :: PrimType ty => ty -> BlockN n ty -> Bool
    elem :: forall ty (n :: Nat). PrimType ty => ty -> BlockN n ty -> Bool
    elem ty
    e BlockN n ty
    b = ty -> Block ty -> Bool
    forall ty. PrimType ty => ty -> Block ty -> Bool
    B.elem ty
    e (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b)

    all :: PrimType ty => (ty -> Bool) -> BlockN n ty -> Bool
    all :: forall ty (n :: Nat).
    PrimType ty =>
    (ty -> Bool) -> BlockN n ty -> Bool
    all ty -> Bool
    p BlockN n ty
    b = (ty -> Bool) -> Block ty -> Bool
    forall ty. PrimType ty => (ty -> Bool) -> Block ty -> Bool
    B.all ty -> Bool
    p (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b)

    any :: PrimType ty => (ty -> Bool) -> BlockN n ty -> Bool
    any :: forall ty (n :: Nat).
    PrimType ty =>
    (ty -> Bool) -> BlockN n ty -> Bool
    any ty -> Bool
    p BlockN n ty
    b = (ty -> Bool) -> Block ty -> Bool
    forall ty. PrimType ty => (ty -> Bool) -> Block ty -> Bool
    B.any ty -> Bool
    p (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b)

    find :: PrimType ty => (ty -> Bool) -> BlockN n ty -> Maybe ty
    find :: forall ty (n :: Nat).
    PrimType ty =>
    (ty -> Bool) -> BlockN n ty -> Maybe ty
    find ty -> Bool
    p BlockN n ty
    b = (ty -> Bool) -> Block ty -> Maybe ty
    forall ty. PrimType ty => (ty -> Bool) -> Block ty -> Maybe ty
    B.find ty -> Bool
    p (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b)

    reverse :: PrimType ty => BlockN n ty -> BlockN n ty
    reverse :: forall ty (n :: Nat). PrimType ty => BlockN n ty -> BlockN n ty
    reverse = Block ty -> BlockN n ty
    forall (n :: Nat) a. Block a -> BlockN n a
    BlockN (Block ty -> BlockN n ty)
    -> (BlockN n ty -> Block ty) -> BlockN n ty -> BlockN n ty
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . Block ty -> Block ty
    forall ty. PrimType ty => Block ty -> Block ty
    B.reverse (Block ty -> Block ty)
    -> (BlockN n ty -> Block ty) -> BlockN n ty -> Block ty
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock

    sortBy :: PrimType ty => (ty -> ty -> Ordering) -> BlockN n ty -> BlockN n ty
    sortBy :: forall ty (n :: Nat).
    PrimType ty =>
    (ty -> ty -> Ordering) -> BlockN n ty -> BlockN n ty
    sortBy ty -> ty -> Ordering
    f BlockN n ty
    b = Block ty -> BlockN n ty
    forall (n :: Nat) a. Block a -> BlockN n a
    BlockN ((ty -> ty -> Ordering) -> Block ty -> Block ty
    forall ty.
    PrimType ty =>
    (ty -> ty -> Ordering) -> Block ty -> Block ty
    B.sortBy ty -> ty -> Ordering
    f (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b))

    intersperse :: (CmpNat n 1 ~ 'GT, PrimType ty) => ty -> BlockN n ty -> BlockN (n+n-1) ty
    intersperse :: forall (n :: Nat) ty.
    (CmpNat n 1 ~ 'GT, PrimType ty) =>
    ty -> BlockN n ty -> BlockN ((n + n) - 1) ty
    intersperse ty
    sep BlockN n ty
    b = Block ty -> BlockN ((n + n) - 1) ty
    forall (n :: Nat) a. Block a -> BlockN n a
    BlockN (ty -> Block ty -> Block ty
    forall ty. PrimType ty => ty -> Block ty -> Block ty
    B.intersperse ty
    sep (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b))

    toCount :: forall n ty . (KnownNat n, Countable ty n) => CountOf ty
    toCount :: forall (n :: Nat) ty. (KnownNat n, Countable ty n) => CountOf ty
    toCount = Proxy n -> CountOf ty
    forall (n :: Nat) ty (proxy :: Nat -> Type).
    (KnownNat n, NatWithinBound (CountOf ty) n) =>
    proxy n -> CountOf ty
    natValCountOf (forall (t :: Nat). Proxy t
    forall {k} (t :: k). Proxy t
    Proxy @n)

    toOffset :: forall n ty . (KnownNat n, Offsetable ty n) => Offset ty
    toOffset :: forall (n :: Nat) ty. (KnownNat n, Offsetable ty n) => Offset ty
    toOffset = Proxy n -> Offset ty
    forall (n :: Nat) ty (proxy :: Nat -> Type).
    (KnownNat n, NatWithinBound (Offset ty) n) =>
    proxy n -> Offset ty
    natValOffset (forall (t :: Nat). Proxy t
    forall {k} (t :: k). Proxy t
    Proxy @n)

    -- | Get a Ptr pointing to the data in the Block.
    --
    -- Since a Block is immutable, this Ptr shouldn't be
    -- to use to modify the contents
    --
    -- If the Block is pinned, then its address is returned as is,
    -- however if it's unpinned, a pinned copy of the Block is made
    -- before getting the address.
    withPtr :: (PrimMonad prim, KnownNat n)
            => BlockN n ty
            -> (Ptr ty -> prim a)
            -> prim a
    withPtr :: forall (prim :: Type -> Type) (n :: Nat) ty a.
    (PrimMonad prim, KnownNat n) =>
    BlockN n ty -> (Ptr ty -> prim a) -> prim a
    withPtr BlockN n ty
    b = Block ty -> (Ptr ty -> prim a) -> prim a
    forall (prim :: Type -> Type) ty a.
    PrimMonad prim =>
    Block ty -> (Ptr ty -> prim a) -> prim a
    B.withPtr (BlockN n ty -> Block ty
    forall (n :: Nat) a. BlockN n a -> Block a
    unBlock BlockN n ty
    b)

    -- | Create a pointer on the beginning of the MutableBlock
    -- and call a function 'f'.
    --
    -- The mutable block can be mutated by the 'f' function
    -- and the change will be reflected in the mutable block
    --
    -- If the mutable block is unpinned, a trampoline buffer
    -- is created and the data is only copied when 'f' return.
    --
    -- it is all-in-all highly inefficient as this cause 2 copies
    withMutablePtr :: (PrimMonad prim, KnownNat n)
                   => MutableBlockN n ty (PrimState prim)
                   -> (Ptr ty -> prim a)
                   -> prim a
    withMutablePtr :: forall (prim :: Type -> Type) (n :: Nat) ty a.
    (PrimMonad prim, KnownNat n) =>
    MutableBlockN n ty (PrimState prim) -> (Ptr ty -> prim a) -> prim a
    withMutablePtr MutableBlockN n ty (PrimState prim)
    mb = MutableBlock ty (PrimState prim) -> (Ptr ty -> prim a) -> prim a
    forall (prim :: Type -> Type) ty a.
    PrimMonad prim =>
    MutableBlock ty (PrimState prim) -> (Ptr ty -> prim a) -> prim a
    B.withMutablePtr (MutableBlockN n ty (PrimState prim)
    -> MutableBlock ty (PrimState prim)
    forall (n :: Nat) ty st.
    MutableBlockN n ty st -> MutableBlock ty st
    unMBlock MutableBlockN n ty (PrimState prim)
    mb)

    -- | Same as 'withMutablePtr' but allow to specify 2 optimisations
    -- which is only useful when the MutableBlock is unpinned and need
    -- a pinned trampoline to be called safely.
    --
    -- If skipCopy is True, then the first copy which happen before
    -- the call to 'f', is skipped. The Ptr is now effectively
    -- pointing to uninitialized data in a new mutable Block.
    --
    -- If skipCopyBack is True, then the second copy which happen after
    -- the call to 'f', is skipped. Then effectively in the case of a
    -- trampoline being used the memory changed by 'f' will not
    -- be reflected in the original Mutable Block.
    --
    -- If using the wrong parameters, it will lead to difficult to
    -- debug issue of corrupted buffer which only present themselves
    -- with certain Mutable Block that happened to have been allocated
    -- unpinned.
    --
    -- If unsure use 'withMutablePtr', which default to *not* skip
    -- any copy.
    withMutablePtrHint :: forall n ty prim a . (PrimMonad prim, KnownNat n)
                       => Bool -- ^ hint that the buffer doesn't need to have the same value as the mutable block when calling f
                       -> Bool -- ^ hint that the buffer is not supposed to be modified by call of f
                       -> MutableBlockN n ty (PrimState prim)
                       -> (Ptr ty -> prim a)
                       -> prim a
    withMutablePtrHint :: forall (n :: Nat) ty (prim :: Type -> Type) a.
    (PrimMonad prim, KnownNat n) =>
    Bool
    -> Bool
    -> MutableBlockN n ty (PrimState prim)
    -> (Ptr ty -> prim a)
    -> prim a
    withMutablePtrHint Bool
    skipCopy Bool
    skipCopyBack (MutableBlockN MutableBlock ty (PrimState prim)
    mb) Ptr ty -> prim a
    f =
        Bool
    -> Bool
    -> MutableBlock ty (PrimState prim)
    -> (Ptr ty -> prim a)
    -> prim a
    forall ty (prim :: Type -> Type) a.
    PrimMonad prim =>
    Bool
    -> Bool
    -> MutableBlock ty (PrimState prim)
    -> (Ptr ty -> prim a)
    -> prim a
    B.withMutablePtrHint Bool
    skipCopy Bool
    skipCopyBack MutableBlock ty (PrimState prim)
    mb Ptr ty -> prim a
    f