4

Haskellは初めてです。Haskellの大前提は、関数が常に同じ値を返すということです。たとえば、テンプレートメタプログラミングを使用してC ++で実行できるように、コンパイル時に定数のフィボナッチ値を計算する方法があると思いますが、それを行う方法がわかりません。方法はありますか?

4

2 に答える 2

9

編集: Daniel Fischer は、通常の式を Template Haskell にリフトし、コンパイル時に結果を評価できることを指摘しています。通常の関数fibを使用してからスプライシングすることにより、出力型に関する特定の制約に従います。

$(let x = fib 1000 in [|x|])

元の答えは次のとおりです。

コメントで指摘されているように、これには Template Haskell が適しています。フィボナッチのような帰納関数の場合は、かなり簡単です。標準定義と同様のコードを記述しますが、ExpQ 値を返します。スプライシングの制限により、2 つのモジュールを使用する必要があります。

{-# LANGUAGE TemplateHaskell #-} 
module TH where

import Language.Haskell.TH

fibTH :: Int -> ExpQ
fibTH 0 = [| 0 |]
fibTH 1 = [| 1 |]
fibTH n = [| $(fibTH (n-1)) + $(fibTH (n-2)) |]

{-# LANGUAGE TemplateHaskell #-}
module Main where

import TH

y :: Int
y = $(fibTH 10)

main = print y

コンパイル時に作業が実行されていることを確認するには、 でコンパイルし-ddump-simplてコアを表示し、それを確認します。

Main.y :: GHC.Types.Int
[GblId,
 Caf=NoCafRefs,
 Str=DmdType m,
 Unf=Unf{Src=<vanilla>, TopLvl=True, Arity=0, Value=True,
         ConLike=True, WorkFree=False, Expandable=True,
         Guidance=IF_ARGS [] 10 20}]
Main.y = GHC.Types.I# 55
于 2012-12-29T08:44:34.227 に答える
5

Don Stewart による素晴らしい記事があり、適切なフラグを選択して LLVM バックエンドを使用すると、コンパイル時に特定の関数が事前計算され、それらが定数に置き換えられることが示されています。

于 2012-12-29T02:39:57.460 に答える