You can't pattern match on a data constructor of a data family like `GMap`

without already knowing it's key type -- i.e. it's not like a GADT, because it's open, so it would be impossible to cover all cases. So if you want to implement a generic show, you need to do it without accessing the representation directly. I have two alternatives for you:

## Catch-all instance

After playing around a little, the simplest way I could come up with was to add a method to the class for use in the instance.

```
class GMapKey k where
data GMap k :: * -> *
empty :: GMap k v
lookup :: k -> GMap k v -> Maybe v
insert :: k -> v -> GMap k v -> GMap k v
showGMap :: (Show v) => GMap k v -> String
```

Then you can make a single general catch-all instance.

```
instance (GMapKey k, Show v) => Show (GMap k v) where
show = showGMap
```

This is a little less smooth than I would desire, but it's not too awfully bad. My main lament with this method is that it precludes `deriving Show`

on the instances, i.e.

```
instance GMapKey Int where
data GMap Int v = GMapInt (Data.IntMap.IntMap v)
deriving (Show)
...
```

is illegal because it overlaps with our catch-all instance. This could be kind of a pain if the type gets complex. The next method does not suffer from this problem.

Anyway, now we have an instance and can use it like usual.

```
example :: (GMapKey k, Show v) => GMap k v -> String
example gmap = show gmap
```

## Dictionary method

If you need to use `deriving Show`

, you could do it a more modern way using the `constraints`

package.

```
{-# LANGUAGE ScopedTypeVariables, TypeApplications #-}
import Data.Constraint
```

It also involves adding a method, but instead of returning a `String`

, it returns a whole `Show`

dictionary.

```
class GMapKey k where
data GMap k :: * -> *
empty :: GMap k v
lookup :: k -> GMap k v -> Maybe v
insert :: k -> v -> GMap k v -> GMap k v
showGMap :: (Show v) => Dict (Show (GMap k v))
```

You can instantiate with `deriving`

, and the `showGMap`

instance is always the same.

```
instance GMapKey Int where
data GMap Int v = GMapInt (Data.IntMap.IntMap v)
deriving (Show)
...
showGMap = Dict
```

(You could even use `DefaultSignatures`

to avoid having to mention `showGMap`

in the instances at all!)

Unfortunately, a catch-all instance will still overlap with this, and so we won't have a global `Show`

instance for `GMap`

s. However, we can manufacture one locally wherever we need it, using `withDict`

```
example :: forall k v. (GMapKey k, Show v) => GMap k v -> String
example gmap = withDict @k @v (show gmap)
```

which is annoying in a different way. Fortunately we only need to do this when we need a *generic* `Show (GMap k v)`

instance -- if we already know what `k`

is then the specific `Show`

instances we derived will work.

Maybe there's a way to get the best of both worlds?