为什么GHC不能针对常数进行优化?

Mai*_*tor 12 optimization haskell ghc

import Data.List
a = foldl' (+) 0 [1..99999999]
main = putStrLn $ show $ a
Run Code Online (Sandbox Code Playgroud)

该程序需要一段时间才能运行.但a不依赖于任何东西,因此是不变的.它可以在编译时完美计算.为什么不对GHC进行优化呢?它是否有一个标志,或者我应该用值本身替换那种常量计算?

lef*_*out 12

这不是一个完美的解决方案,但正如kqr已经说过的那样,你当然可以通过Template Haskell实现你的目标:

{-# LANGUAGE TemplateHaskell #-}

import Language.Haskell.TH
import Data.List

a :: Integer
a = $( return . LitE . IntegerL $ foldl' (+) 0 [1..99999999] )

main = print a
Run Code Online (Sandbox Code Playgroud)

4999999950000000在实际开始编译程序之前,这将从fold表达式生成整数文字.


Mih*_*eac 7

这与此reddit线程所涵盖的讨论相同.基本上,你想要的只是一个在实践中不常见的简单案例.通过恒定折叠进行优化很快就会成为关于哥德尔定理和停止问题的问题.

  • 为什么不能只有一个pragma说"在编译时计算这个",以便证明终止的责任在程序员身上? (5认同)
  • 这对我来说没问题.如果我不知道它是否会终止,我不介意.就像我说的那样,担心终止程序员的负担,我很高兴等到我厌倦了等待. (5认同)
  • 我不明白这是怎么回事.我要问的是编译器编译指示,它告诉`ghc`尝试在编译时计算值.如果它没有终止,那我就没事了. (4认同)
  • 我不知道我是对的,但没关系.就像我说的那样,让我担心.毕竟,Haskell已经有了"UndecidableInstances",它将可判定性证明的负担转移给了程序员,为什么这有什么不同呢?让程序员担心它是否可判定. (4认同)
  • @MihaiMaruseac人为提供的注释是一种相对常见的策略,用于为编译器提供有关个别特殊情况的事实,这些特殊情况通常无法自动推断。实际上,`unsafePerformIO`和朋友就是这样;通过使用它们,您断言可以执行此特定的IO操作,就好像它是一个纯函数一样,如果您做错了,那么造成的灾难就是您的问题。相同事物的Mercury版本明确称为“ promises”,甚至有一个关于终止分析的版本。 (2认同)