Pergunta

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.

Foi útil?

Solução

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top