haskell - 当构造函数静态已知时消除 GADT 上的模式匹配

标签 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 在运行时忽略任何模式匹配并假设实际分支是静态已知的来生成代码?

最佳答案

当 GHC 编译 printMyGADT 时,类型索引 a 当然是未知的(它是一个变量),并且有关 a 的信息不可用在运行时,所以 printMyMyGADT 必须在它传递的构造函数上执行一个分支。

如果你有的话

printMyMyGADT' :: MyGADT IntConstructor -> IO ()
printMyMyGADT' (MyInt i) = printInteger i

然后 GHC 能够将只有 MyInt 构造函数可能的信息传播到生成的代码,并避免构造函数上的分支。

如果您在已知类型变量 aIntConstructor 的上下文中调用原始 printMyGADT,并且如果它是inlined 那么 GHC 会将内联表达式简化为 printMyMyGADT' ,并且分支将再次被避免。我不确定这也可能适用于特化。

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

关于haskell - 当构造函数静态已知时消除 GADT 上的模式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39742720/

相关文章:

haskell - 函数依赖和重叠实例

haskell - 使用 FFI 的可执行文件是否需要 GHC 选项?

c - 神秘的内存管理

c++ - 手动 SIMD 代码的可负担性

c - 在没有副作用的情况下对 bool 操作数进行短路

haskell - 将 haskell 代码概括/编译为 lambda

Haskell 从对列表到列表对

haskell - 不能从这个表达式导出(显示)

string - 将字符串转换为数字并打印到命令行

haskell - Rich Hickey 不使用自动柯里化(Currying) Clojure 函数的原因是什么?