当构造函数静态地知道时,消除GADT上的模式匹配

时间:2016-09-28 09:03:36

标签: haskell ghc compiler-optimization algebraic-data-types

假设我推广了数据类型:

data GADTConstructor = IntConstructor | StringConstructor

然后我创建了GADT:

data MyGADT (a :: GADTConstructor) where
    MyInt    :: Int -> MyGADT IntConstructor
    MyString :: String -> MyGADT StringConstructor

和模式匹配功能:

printMyMyGADT :: MyGADT a -> IO ()
printMyMyGADT (MyInt i) = printInteger i
printMyMyGADT (MyString s) = printString s

这里实际的GADT构造函数由GADT的类型索引唯一确定,该索引在编译时是已知的。是否可以强制GHC在运行时省略任何模式匹配并生成代码,假设实际分支是静态已知的?

1 个答案:

答案 0 :(得分:3)

当GHC编译printMyMyGADT时,类型索引a当然不知道(它是变量),而且a的信息在运行时也不可用,所以{ {1}}必须做一个传递构造函数的分支。

如果你有

printMyMyGADT

然后GHC能够将只有printMyMyGADT' :: MyGADT IntConstructor -> IO () printMyMyGADT' (MyInt i) = printInteger i 构造函数的信息传播到生成的代码中,并避免构造函数上的分支。

如果您在其类型变量MyInt已知为printMyMyGADT的上下文中调用原始a如果内联则GHC将简化内联表达式为IntConstructor,并且将避免分支。这可能也适用于专业化,我不确定。

所有这些在实践中都是无关紧要的,因为在所有情况下printMyMyGADT'都需要处理传递未评估表达式的情况。我们看到的两个构造函数中的分支成本不会超过检查我们是否首先通过构造函数的成本。