为什么在Haskell编译时不会评估(常量)表达式? [英] Why are (constant) expressions not evaluated at compile time in Haskell?

查看:165
本文介绍了为什么在Haskell编译时不会评估(常量)表达式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



当我构建一个复杂的表达式(其计算需要一些时间)并且这个表达式是不变的(意味着它只是构建已知的硬编码值),表达式不会在编译时计算。



从C / C ++背景中输入我用到这种类型的优化。



在Haskell / GHC中, NOT 执行这种优化(默认情况下)的原因是什么?什么是优点,如果有的话?

数据树a =
EmptyTree
|节点a(Tree a)(Tree a)
派生(Show,Read,Eq)

elementToTree :: a - >树a
elementToTree x =节点x EmptyTree EmptyTree

treeInsert ::(Ord a)=> a - >树a - >树a
treeInsert x EmptyTree = elementToTree x
treeInsert x(节点左右)
| x == a = Node x左右
| x < a =节点a(treeInsert x left)右边
| x> a =节点左(treeInsert x右)

treeFromList ::(Ord a)=> [a] - >树a
treeFromList [] = EmptyTree
treeFromList(x:xs)= treeInsert x(treeFromList xs)

treeElem ::(Ord a)=> a - >树a - > Bool
treeElem x EmptyTree = False
treeElem x(节点左右)
| x == a =真
| x < a = treeElem x离开
| x> a = treeElem x right

main = do
let tree = treeFromList [0..90000]
putStrLn $ show(treeElem 3 tree)

因为这会始终 打印真实我期望编译的程序几乎可以立即打印并退出
您可能会喜欢这是reddit线程。编译器可以尝试做到这一点,但它可能是危险的,因为任何类型的常量都可以做循环等有趣的事情。至少有两种解决方案:一种是超级编译,不能作为任何编译器的一部分,但您可以尝试各种研究人员的原型;更实用的是使用Template Haskell,这是GHC让程序员要求在编译时运行一些代码的机制。


I am currently learning Haskell, and there is one thing that baffles me:

When I build a complex expression (whose computation will take some time) and this expression is constant (meaning it is build only of known, hard coded values), the expression is not evaluated at compile time.

Comming from a C/C++ background I am used to such kind of optimization.

What is the reason to NOT perform such optimization (by default) in Haskell / GHC ? What are the advantages, if any?

data Tree a =
   EmptyTree
 | Node a (Tree a) (Tree a)
 deriving (Show, Read, Eq)

elementToTree :: a -> Tree a
elementToTree x = Node x EmptyTree EmptyTree

treeInsert :: (Ord a) => a -> Tree a -> Tree a
treeInsert x EmptyTree = elementToTree x
treeInsert x (Node a left right)
  | x == a = Node x left right
  | x < a  = Node a (treeInsert x left) right
  | x > a  = Node a left (treeInsert x right)

treeFromList :: (Ord a) => [a] -> Tree a
treeFromList []     = EmptyTree
treeFromList (x:xs) = treeInsert x (treeFromList xs)

treeElem :: (Ord a) => a -> Tree a -> Bool
treeElem x EmptyTree = False
treeElem x (Node a left right)
  | x == a = True
  | x < a  = treeElem x left
  | x > a  = treeElem x right

main = do
  let tree = treeFromList [0..90000]
  putStrLn $ show (treeElem 3 tree)

As this will always print True I would expect the compiled programm to print and exit almost immediately.

解决方案

You may like this reddit thread. The compiler could try to do this, but it could be dangerous, as constants of any type can do funny things like loop. There are at least two solutions: one is supercompilation, not available as part of any compiler yet but you can try prototypes from various researchers; the more practical one is to use Template Haskell, which is GHC's mechanism for letting the programmer ask for some code to be run at compile time.

这篇关于为什么在Haskell编译时不会评估(常量)表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆