Skip to content

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) `

Edited by Icelandjack
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information