Foreign.Storable.Traversable

storable-record-0.0.7: Elegant definition of Storable instances for records

Safe Haskell | Safe-Inferred
Language | Haskell98

Foreign.Storable.Traversable

Description

If you have a `Traversable` instance of a record, you can load and store all elements, that are accessible by `Traversable` methods. We treat the record like an array, that is we assume, that all elements have the same size and alignment.

Example:

    import Foreign.Storable.Traversable as Store

    data Stereo a = Stereo {left, right :: a}

    instance Functor Stereo where
       fmap = Trav.fmapDefault

    instance Foldable Stereo where
       foldMap = Trav.foldMapDefault

    instance Traversable Stereo where
       sequenceA ~(Stereo l r) = liftA2 Stereo l r

    instance (Storable a) => Storable (Stereo a) where
       sizeOf = Store.sizeOf
       alignment = Store.alignment
       peek = Store.peek (error "instance Traversable Stereo is lazy, so we do not provide a real value here")
       poke = Store.poke

You would certainly not define the `Traversable` and according instances just for the implementation of the `Storable` instance, but there are usually similar applications where the `Traversable` instance is useful.

Synopsis

- alignment :: (Foldable f, Storable a) => f a -> Int
- sizeOf :: (Foldable f, Storable a) => f a -> Int
- peek :: (Traversable f, Storable a) => f () -> Ptr (f a) -> IO (f a)
- poke :: (Foldable f, Storable a) => Ptr (f a) -> f a -> IO ()
- peekApplicative :: (Applicative f, Traversable f, Storable a) => Ptr (f a) -> IO (f a)

# Documentation

alignment :: (Foldable f, Storable a) => f a -> Int #

sizeOf :: (Foldable f, Storable a) => f a -> Int #

Warning: It uses Foldable class and will certainly access the data structure and thus will fail on `undefined`.

You may call it on the record, after re-constructing it lazily:

    sizeOf . lazy

    lazy :: Complex a -> Complex a
    lazy ~(r:+i) = r:+i

peek :: (Traversable f, Storable a) => f () -> Ptr (f a) -> IO (f a) #

`peek skeleton ptr` fills the `skeleton` with data read from memory beginning at `ptr`. The skeleton is needed formally for using `Traversable`. For instance when reading a list, it is not clear, how many elements shall be read. Using the skeleton you can give this information and you also provide information that is not contained in the element type `a`. For example you can call

    peek (replicate 10 ()) ptr

for reading 10 elements from memory starting at `ptr`.

poke :: (Foldable f, Storable a) => Ptr (f a) -> f a -> IO () #

peekApplicative :: (Applicative f, Traversable f, Storable a) => Ptr (f a) -> IO (f a) #

Like `peek` but uses `pure` for construction of the result. `pure` would be in class `Pointed` if that would exist. Thus we use the closest approximate `Applicative`.