Let's say I have a polymorphic type where one of the parameters is a higher-kinded type (* -> *
).
data Tricky m = Tricky { numbers :: m Int, genesis :: m String }
Is there a general way of deriving instances for such types without using arcane and unsafe language extensions?
I tried enabling StandaloneDeriving
so that I could specify the context:
deriving instance Show (m Int) => Show (Tricky m)
But GHC then complains about the constraint being no smaller than the instance head, and points me in the direction of UndecidableInstances
.
To summarise:
1. Should I simply go along with this advice, or is there a better way?
2. Are there any proposals to make this process easier?
3. Is it somehow wrong-headed to want to derive 'higher-kinded' instances? Would it be better to derive instances for a few concrete types instead (eg. Vector
, []
, Set
)
1. There's nothing unsafe about UndecidableInstances
.
There's another way to define Show (Tricky m)
, which is to require the m
satisfies forall a. Show a => Show (m a)
. This is captured by a typeclass like
class Show1 f where
showsPrec1 :: Show a => Int -> f a -> ShowS
An even cleverer version of Show1
has been added to base 4.9. It's more general since it can be used to show an m a
when a
doesn't have a Show a
instance.
2. You've found the right bits and pieces for doing this.
3. No, it's right-headed to abstract over even higher-kinded structures like Vector
, []
, and Set
. Monad transformers have the kind (* -> *) -> (* -> *)
and abstract over types of kind (* -> *)
, the same kind as a functor, to produce types with the same kind as a functor. Tricky
has kind (* -> *) -> *
, it takes something with the same kind as a functor and produces an ordinary data type. I call data types of this kind "Models" since they produce a data type abstracting over how it is put together.
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