假设我推广了数据类型:
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在运行时省略任何模式匹配并生成代码,假设实际分支是静态已知的?
答案 0 :(得分:3)
当GHC编译printMyMyGADT
时,类型索引a
当然不知道(它是变量),而且a
的信息在运行时也不可用,所以{ {1}}必须做一个传递构造函数的分支。
如果你有
printMyMyGADT
然后GHC能够将只有printMyMyGADT' :: MyGADT IntConstructor -> IO ()
printMyMyGADT' (MyInt i) = printInteger i
构造函数的信息传播到生成的代码中,并避免构造函数上的分支。
如果您在其类型变量MyInt
已知为printMyMyGADT
的上下文中调用原始a
而如果内联则GHC将简化内联表达式为IntConstructor
,并且将避免分支。这可能也适用于专业化,我不确定。
所有这些在实践中都是无关紧要的,因为在所有情况下printMyMyGADT'
都需要处理传递未评估表达式的情况。我们看到的两个构造函数中的分支成本不会超过检查我们是否首先通过构造函数的成本。