I want to write a Convertible instance for a Haskell type to its C representation
It looks like this:
instance Convertible Variable (IO (Ptr ())) where
Now GHC complains:
Illegal instance declaration for `Convertible
Variable (IO (Ptr ()))'
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Use -XFlexibleInstances if you want to disable this.)
In the instance declaration for `Convertible Variable (IO (Ptr ()))'
I thought Flexible Instances were needed if you had free types in your instance declaration, but this is not the case. I can get it to compile when adding the right pragma, but can anyone explain why I need this?
You can often avoid FlexibleInstances
in cases like this. There are two general approaches:
instance ConvIO a => Convertible Variable (IO a) where
method = methodIO
class ConvIO p where
methodIO :: ...
-- similar to the signature for the Convertible method,
-- but with Variable and IO baked in
instance ConvIOPtr u => ConvIO (Ptr u) where
methodIO = methodIOPtr
class ConvIOPtr u where
methodIOPtr :: ...
instance ConvIOPtr () where ...
This approach works well when you need several instances headed by the same constructor.
Turn on GADTs
or TypeFamilies
and write
instance a ~ Ptr () => Convertible Variable (IO a) where ...
This approach tends to help a lot with type inference, but only makes sense if you only need one instance headed by IO
.
You can use an auxiliary class to go through IO
, and then an equality constraint to go through Ptr
.
instance u ~ () => ConvIO (Ptr u) where ...
Or you can use an equality constraint to go through IO
and an auxiliary class to go through Ptr
:
instance (a ~ Ptr u, ConvIOPtr u) => Convertible Variable (IO a)
If you need an instance one of whose arguments is a type variable, then you really can't avoid FlexibleInstances
at all. You might be able to work around the problem using a newtype, but it's not worth the trouble.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With