簡體   English   中英

Haskell編譯時函數計算

[英]Haskell compile time function calculation

我想在編譯時預先計算函數的值。

示例(實際功能更復雜,沒有嘗試編譯):

base = 10
mymodulus n = n `mod` base -- or substitute with a function that takes
                            -- too much to compute at runtime
printmodules 0 = [mymodulus 0]
printmodules z = (mymodulus z):(printmodules (z-1))

main = printmodules 64

知道只有n < 64才能調用mymodulus n ,並且我想在編譯時預先計算mymodulusn值為0..64 原因是mymodulus非常昂貴並且會多次重復使用。

你應該使用Template Haskell 使用TH,您可以在編譯時以編程方式生成代碼。 在這種情況下,你的mymodulus實際上是一個“模板”。

例如,我們可以按如下方式重寫您的程序,以靜態計算您的函數。 首先,主代碼像往常一樣,但它不是調用你的模數函數,而是調用一個函數,它的主體是一個將在編譯時生成的拼接:

{-# LANGUAGE TemplateHaskell #-}

import Table

mymodulus n = $(genmodulus 64)

main = mapM_ (print . mymodulus) [0..64]

以及靜態生成表的代碼:

{-# LANGUAGE TemplateHaskell #-}

module Table where

import Language.Haskell.TH
import Language.Haskell.TH.Syntax

genmodulus :: Int -> Q Exp
genmodulus n = return $ CaseE (VarE (mkName "n"))
                              [ Match (LitP (IntegerL i))
                                      (NormalB (LitE (IntegerL (i `mod` base))))
                                      []
                              | i <- [0..fromIntegral n] ]
    where
        base = 10

這描述了case表達式的抽象語法,它將在編譯時生成。 我們只是生成一個大開關:

    genmodulus 64
  ======>
    case n of {
      0 -> 0
      1 -> 1
      2 -> 2
      3 -> 3
      4 -> 4
      ...
      64 -> 4 }

您可以看到使用-ddump-splices生成的代碼。 我以直接的方式編寫了模板代碼。 更熟悉TH的人應該能夠使模式代碼更簡單。

另一種選擇是離線生成值表,並只導入該數據結構。

您也可以說為什么要這樣做。 我假設你有一個非常復雜的表驅動函數?

我不知道有任何方法可以將它預編譯到表查找中(盡管你可能對TH有一些好運)​​。 另一種方法是在運行時使用類似的方法生成查找表

mymodulus' x = lt ! x
    where lt = array (0, 64) [(i, mymodulus i) | i <- [0..64]]

我記得有一些特殊的行為附加到頂級定義。 如果你試試簡單的例子:

primes = 2 : 3 : filter isPrime [5, 7 .. 1000000]
isPrime x = walk (tail primes) where
    walk (y:ys) | (y*y > x) = True
                | (x `mod` y) /= 0 = walk ys
    walk _ = False
main = do
    print $ last primes
    print . last $ init primes

你會看到(最后一個素數)的第一次調用將啟動素數的計算,第二行將重用這些計算。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM