Haskell расширил определенные thunks во время компиляции?

Есть ли способ заставить Haskell расширять определенные thunks во время выполнения. Например, скажем, у меня есть

--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 ответ

Решение

Это довольно просто с шаблоном 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
Другие вопросы по тегам