Search code examples
haskellpolymorphismexistential-typeheterogeneous

Haskell heterogeneous list of Storable objects


I want to write function that can poke heterogeneous list of Storable objects (different types)

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes, ExistentialQuantification, ImpredicativeTypes #-}

pokeMany :: Ptr b -> Int -> [forall a. Storable a => a] -> IO ()
pokeMany _ _ [] = return ()
pokeMany ptr offset (x:xs) = do
    pokeByteOff ptr offset x
    pokeMany ptr (offset + sizeOf x) xs

somePoke :: Ptr a -> Int -> Int -> IO ()
somePoke ptr x1 x2 = pokeMany ptr 0 [x1, x2]

But I get compile errors:

No instance for (Storable a1) arising from a use of `sizeOf'
The type variable `a1' is ambiguous
Note: there are several potential instances:
  instance Storable CChar -- Defined in `Foreign.C.Types'
  instance Storable CClock -- Defined in `Foreign.C.Types'
  instance Storable CDouble -- Defined in `Foreign.C.Types'

Couldn't match expected type `a2' with actual type `Int'
  `a2' is a rigid type variable bound by
       a type expected by the context: Storable a2 => a2

and others ...

Then I create some data type

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes, ExistentialQuantification, ImpredicativeTypes #-}

data AnyStorable = forall a. Storable a => AnyStorable a

pokeMany :: Ptr b -> Int -> [AnyStorable] -> IO ()
pokeMany _ _ [] = return ()
pokeMany ptr offset (AnyStorable x:xs) = do
    pokeByteOff ptr offset x
    pokeMany ptr (offset + sizeOf x) xs

somePoke :: Ptr a -> Int -> Int -> IO ()
somePoke ptr n c = pokeMany ptr 0 [AnyStorable n, AnyStorable c, AnyStorable 'a']

The code above hasn't any compile errors.

Can I write pokeMany function without creating new data type like AnyStorable?


Solution

  • In short, no. What you'd need for that would be exists keyword to specify the signature of the function that'll be mapped on the collection. Using forall in the datatype effectively expresses the same from the other side.

    BTW, you might consider making AnyStorable an instance of Storable.