让Haskell在编译时扩展某些thunk?

时间:2014-03-30 22:50:02

标签: haskell compilation evaluation thunk

有没有办法让Haskell在运行时扩展某些thunk。例如,说我有

--Purposely inefficient code for demonstration
fib 0=0
fib 1=1
fib n=fib n=fib (n-1) + fib (n-2)
goldRatio=fib 100 / fib 101

我怎样才能在编译时评估goldRatio。例如,使用

{-# EVALUATE goldRatio #-}

它只需要弱头形式,因为Control.Deepseq.force可以处理其余部分。我听说模板haskell可以做到这一点,但我不太清楚。

注意:我现在正在使用GHC。

1 个答案:

答案 0 :(得分:9)

使用模板haskell非常简单。首先,在一个模块中定义代码:

module Test where
--Purposely inefficient code for demonstration
fib 0=0
fib 1=1
fib n=fib (n-1) + fib (n-2)

然后在另一个模块中使用带有模板haskell的代码创建值。您必须在另一个模块中执行此操作,因为模板haskell定义无法调用在同一模块中定义的函数。

{-# LANGUAGE TemplateHaskell #-}
import Test
import Language.Haskell.TH
import Data.Ratio

goldRatio :: Double
goldRatio = $(litE (rationalL (toRational $ fib 21 / fib 20)))

现在编译将花费更长时间,但goldRatio现在将是固定值并在运行时立即计算。它就像在源代码中键入goldRatio = 1.6180339985218033一样运行。使用示例:

> goldRatio
1.6180339985218033