Specialization fails if dictionaries are represented by unreduced type families.
## Summary
For a function `specMe` like this:
```hs
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE ImplicitParams #-}
module SpecTyFam_Import (specMe, MaybeShowNum) where
import Data.Kind
type family MaybeShowNum a n :: Constraint where
MaybeShowNum a n = (Show a, Num n)
{-# INLINABLE specMe #-}
specMe :: (Integral n, MaybeShowNum a n) => a -> n -> (String,n)
specMe s !n = (show s, n+1 `div` 2)
```
The Specialiser will fail to specialise at a use site like this:
```hs
{-# OPTIONS_GHC -fspecialise-aggressively #-}
{-# OPTIONS_GHC -fno-spec-constr #-}
module SpecTyFam(main, foo) where
import SpecTyFam_Import (specMe, MaybeShowNum)
import GHC.Exts
-- We want to see a specialization of `specMe` which doesn't take a dictionary at runtime.
{-# OPAQUE foo #-}
foo :: Int -> (String,Int)
foo x = specMe True x
main = print $ sum $ map (snd . foo) [1..1000 :: Int]
```
Despite specMe being applied to a fixed type/dictionary it won't get specialised.
Why? Look at the type of `specMe`, remembering that `MaybeShowNum` is a type family:
```hs
specMe :: (Integral n, MaybeShowNum a n) => a -> n -> (String,n)
```
Currently GHC looks at the **type** of the argument, `MaybeShowNum Bool Int`. Worried that there might be an implicit parameter (on which we must not specialise) hiding inside the type instance, it conservatively declines to specialise.
But the *actual argument* looks like `(d1, d2) |> co`, where `d1::Show Bool` and `d2::Num Int`, which is patently OK, a big lost opportunity. See also this comment https://gitlab.haskell.org/ghc/ghc/-/issues/19747#note_620466 and the surrounding comments on #19747 which is where I discovered this bug.
A fix which will inspect the *term* argument as well as the type is in the works in https://gitlab.haskell.org/ghc/ghc/-/merge_requests/14272
## Environment
* GHC version used: ghc-9.0 - 9.12.2
issue