Is there a way to have Haskell expand certain thunks at run time. For example, say I have
--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
How could I have it evaluate goldRatio
at compile time. Like for example, with
{-# EVALUATE goldRatio #-}
It would only need to be to weak head form, since Control.Deepseq.force
could handle the rest. I hear template haskell can do this, but I do not know it well.
Note: I am using GHC at the moment.
This is pretty simple with template haskell. Firstly, define the code in one module:
module Test where
--Purposely inefficient code for demonstration
fib 0=0
fib 1=1
fib n=fib (n-1) + fib (n-2)
Then create the value using that code with template haskell in another module. You have to do it in another module as template haskell definitions cannot call functions defined in the same module.
{-# LANGUAGE TemplateHaskell #-}
import Test
import Language.Haskell.TH
import Data.Ratio
goldRatio :: Double
goldRatio = $(litE (rationalL (toRational $ fib 21 / fib 20)))
Now compiling will take longer, however goldRatio
will now be a fixed value and compute instantly at runtime. It runs as if you typed goldRatio = 1.6180339985218033
in the source code. Example use:
> goldRatio
1.6180339985218033