concat :: forall ty . PrimType ty => [UArray ty] -> UArray ty
concat original = runST $ do
    r <- new total
    goCopy r 0 original
    unsafeFreeze r
  where
    !total = size 0 original
    -- size
    size !sz []     = sz
    size !sz (x:xs) = size (length x + sz) xs

    zero = Offset 0

    goCopy r = loop
      where
        loop _  []      = pure ()
        loop !i (x:xs) = do
            unsafeCopyAtRO r i x zero lx
            loop (i `offsetPlusE` lx) xs
          where !lx = length x

-- | Create a Block from a UArray.
--
-- Note that because of the slice, the destination block
-- is re-allocated and copied, unless the slice point
-- at the whole array
concat :: forall ty . PrimType ty => [UArray ty] -> UArray ty
concat original = runST $ do
    r <- new total
    goCopy r 0 original
    unsafeFreeze r
  where
    !total = size 0 original
    -- size
    size !sz []     = sz
    size !sz (x:xs) = size (length x + sz) xs

    zero = Offset 0

    goCopy r = loop
      where
        loop _  []      = pure ()
        loop !i (x:xs) = do
            unsafeCopyAtRO r i x zero lx
            loop (i `offsetPlusE` lx) xs
          where !lx = length x

-- | Create a Block from a UArray.
--
-- Note that because of the slice, the destination block
-- is re-allocated and copied, unless the slice point
-- at the whole array
concat original = runST $ do
    r <- new total
    goCopy r 0 original
    unsafeFreeze r
  where
    !total = size 0 original
    -- size
    size !sz []     = sz
    size !sz (x:xs) = size (length x + sz) xs

    zero = Offset 0

    goCopy r = loop
      where
        loop _  []      = pure ()
        loop !i (x:xs) = do
            unsafeCopyAtRO r i x zero lx
            loop (i `offsetPlusE` lx) xs
          where !lx = length x

-- | Create a Block from a UArray.
--
-- Note that because of the slice, the destination block
-- is re-allocated and copied, unless the slice point
-- at the whole array