sendFromSingleValue :: (Repr v, Storable v) => v -> (Ptr e -> CInt -> Datatype -> IO a) -> IO a
sendFromSingleValue v f = do
  alloca $ \ptr -> do
    poke ptr v
    let (1, dtype) = representation v
    f (castPtr ptr) (1::CInt) dtype

-- | Sending from Storable arrays requres knowing MPI representation 'Repr' of its elements. This is very
-- fast and efficient, since array would be updated in-place.
sendFromSingleValue :: (Repr v, Storable v) => v -> (Ptr e -> CInt -> Datatype -> IO a) -> IO a
sendFromSingleValue v f = do
  alloca $ \ptr -> do
    poke ptr v
    let (1, dtype) = representation v
    f (castPtr ptr) (1::CInt) dtype

-- | Sending from Storable arrays requres knowing MPI representation 'Repr' of its elements. This is very
-- fast and efficient, since array would be updated in-place.
sendFromSingleValue v f = do
  alloca $ \ptr -> do
    poke ptr v
    let (1, dtype) = representation v
    f (castPtr ptr) (1::CInt) dtype

-- | Sending from Storable arrays requres knowing MPI representation 'Repr' of its elements. This is very
-- fast and efficient, since array would be updated in-place.