I have a type class named ManagedValue defined as follows:
class ManagedValue a where
type ManagedPtr a = (r :: *) | r -> a
withManaged :: a -> (ManagedPtr a -> IO b) -> IO b
getManaged :: ManagedPtr a -> IO a
castManagedToPtr :: ManagedPtr a -> Ptr b
castPtrToManaged :: Ptr b -> ManagedPtr a
For every type that is an instance of Storable typeclass, it is also an instance of ManagedValue typeclass, but not all ManagedValues are storable. However, I can't define it as something like instance Storable a => ManagedPtr a where ... becasue GHC gives the error The constraint ‘Storable a’ is no smaller than the instance head ‘ManagedValue a’.
I know I can define a type class hierarchy as Num to Intergral like class (Storable a, ManagedValue a) => StorableValue a where .... But this way needs to define all the instances manually, which is tiresome.
What I want is to declare that all Storable values are also ManagedValue so that I can define an instance just in one place and get the implementations for Int, Double and so on automatically, something like:
-- This definition doesn't work
instance Storable a => ManagedValue a where
type ManagedPtr a = Ptr a
withManaged v f = do
fp <- mallocForeignPtr
withForeignPtr fp $ \p -> do
poke p v
f p
getManaged p = peek p
castManagedToPtr = castPtr
castPtrToManaged = castPtr
Then I can implement the methods of ManagedValue for Int, Double, et al.
Thanks for any tips!