Skip to content

Type families interfere with specialisation rewrite rules

Consider the attached file, in particular the function

vinr :: Length as -> VSum bs -> VSum (as ++ bs)

its specialised version

vinr0 :: Length '[] -> VSum as -> VSum as

and the rewrite rule

{-# RULES "vinr/0" vinr = vinr0 #-}

According to the relevant section of GHC user guide, vinr should be replaced with vinr0 whenever the types match. However, the resulting Core for test contains the following (compiled with ghc -O2):

Test.test1
  = case extractIdx
           @ 'Z @ '[Int] @ Int (Test.$WIZ @ Int @ '[]) Test.test2
    of {
      Left other_aZf ->
        Test.$wvinl @ Length @ '[Int] @ (Remove 'Z '[Int]) other_aZf;
      Right x_aZg ->
        vinr
          @ (Remove 'Z '[Int])
          @ '[Int]
          (Test.$WLZ
           `cast` ((Length (Sym (Test.D:R:Remove[0] <Int>_N <'[]>_N)))_R
                   :: (Length '[] :: *) ~R# (Length (Remove 'Z '[Int]) :: *)))
          (Test.VInL
             @ '[Int]
             @ Int
             @ '[]
             @~ (<'[Int]>_N :: ('[Int] :: [*]) GHC.Prim.~# ('[Int] :: [*]))
             x_aZg)
    }

So the rule never fires, and vinr is still there, even though it is directly applied to LZ :: Length '[].

My dilettante analysis is that, for some reason, GHC keeps the Remove 'Z '[Int] as-is, not evaluating it to '[], and, since the types don't match //syntactically//, doesn't apply the rule. In particular, if I replace type families with classes with functional dependencies, the rule fires as expected.

Trac metadata
Trac field Value
Version 8.2.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information