GHCi command to list instances a (possibly compound) type belongs to
This command (:instances
) would be very useful to me (for deriving in particular). People on Twitter were digging it, I believe some are interested in implementing it
>> import Data.Functor.Sum (Sum)
>>
>> :instances Sum [] []
Eq a => Eq (Sum [] [] a)
Ord a => Ord (Sum [] [] a)
Show a => Show (Sum [] [] a)
Read a => Read (Sum [] [] a)
Functor (Sum [] [])
Foldable (Sum [] [])
Eq1 (Sum [] [])
Ord1 (Sum [] [])
Show1 (Sum [] [])
Read1 (Sum [] [])
FunctorWithIndex (Either Int Int) (Sum [] [])
FoldableWithIndex (Either Int Int) (Sum [] [])
TraversableWithIndex (Either Int Int) (Sum [] [])
Not a precise algorithm, but the command :instances <ty>
lists what classes <ty>
is an instance of. This is something I usually do by hand and is useful for finding what instances I can expect to derive with -XDerivingVia
:
data ...
deriving (???)
via (F A B)
-- >> :instances F A B
-- Cls1 (F A B)
-- Cls2 (F A B) ..
data ...
deriving (Cls1, Cls2, ..)
via (F A B)
I expect something like :instances Sum Endo
to return no instances, but I currently rely on my own mind to derive a contradiction for each type. I would cross-reference :info Sum
, :info Endo
which blows up when the types are complex and deeply nested.
partial type signature (`_`) | the command `:instances Either _ Int` should match `Eq a => Eq (Either a Int)` |
---|---|
trace info | I find it noisy but we can |
`
:instances Sum [] [] .. Functor (Sum [] []) -- (Functor f, Functor g) => Functor (Sum f g) -- Defined in ‘Data.Functor.Sum’ .. `
This would be more natural in a interactive environment where we can toggle/expand and collapse it (see #15613 for what might appear as we expand instances).
negative results | There is a `.. => Comonad (Sum f g)` instance but we don't have `Comonad (Sum [] [])` because there is no `Comonad []`. It may be valuable to query negative results |
---|
`
:noinstance Sum [] [] NO (instance Comonad (Sum [] [])) because NO (instance Comonad []) `
multi-parameter type class | I cheekily listed `FunctorWithIndex` example of, I am fine dropping MPTCs, we can also consider special constraints like `Coercible` |
---|
`
newtype List_or_List a = L_or_L (Sum [] [] a)
:instance Sum [] [] .. Coercible (Sum [] [] a) (List_or_List a) `