我是Haskell的新手。鑑於Haskell的整個前提是一個函數總是會返回相同的值,所以我希望有一些例如在編譯時計算常量的斐波那契數值,就像我可以在C++中使用模板metaprogrmming所做的那樣,但我看不出如何去做。有沒有辦法?Haskell變體模板元編程
回答
編輯:丹尼爾菲捨爾指出可以解除一個普通的表達成模板Haskell和評估在編譯時的結果,但須在輸出類型的某些約束,由具有通常的功能fib
然後接合
$(let x = fib 1000 in [|x|])
原始答案如下。
正如在評論中指出的,模板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
在另一個模塊中有一個普通的'fib'函數,然後拼接'y = $(let x = fib 1000 in [| x |])''是不是更好? –
@DanielFischer我不認爲這樣做,這是更好。 –
Don Stewart有一個great article他在那裏表明,使用具有正確標誌選擇的LLVM後端將在編譯時預先計算某些函數並將其替換爲常量。
嗯,有點類似,但它似乎相當試驗和錯誤(雖然有組織地如此)而不是直接確定性。 C++模板更多的是後者;所見即所得,我希望能有更多這樣的解決方案。 – lobsterism
@lobsterism然後你想要模板哈斯克爾。我只提到這個解決方案,因爲你在問我們爲什麼不能利用函數的純度來預編譯它們。然而,Haskell模板根本不利用純度,甚至有副作用。 –
- 1. 模板元編程規則
- 2. 模板元編程問題
- 3. 模板元編程:基元遞歸?
- 4. 編寫遞歸模板haskell函數
- 5. Haskell/Julius模板 - 不能拼接變量
- 6. 使用元編程和可變模板填充靜態模板陣列
- 7. 模板編程
- 8. 分析模板Haskell
- 9. 模板元編程GCC錯誤
- 10. C++使用模板元編程
- 11. 代理模板元編程的問題
- 12. has_member_of_type - C++中的模板元編程
- 13. 模板元編程OR操作
- 14. 模板元編程中的匹配變量C++
- 15. 使用模板函數的C++模板元編程
- 16. XHTML模板編程
- 17. D編程模板
- 18. 什麼樣的C++模板編程可以稱爲「元編程」?
- 19. 如何編譯CUDA牛頓模板元編程示例程序
- 20. 替換爲模板元編程中的三元運算符
- 21. 使用模板元編程計算數據編譯時間
- 22. 元編程模板遞歸不遞歸(編輯重要)
- 23. 在編譯時檢測typedef(模板元編程)
- 24. Data.Map的編輯元素haskell
- 25. 訪問T4模板編程
- 26. 模板編程與位域
- 27. C++中的模板編程
- 28. 如何使用模板Haskell獲取函數的主體?
- 29. Boost遞歸變體以及模板C++
- 30. Wordpress模板字體顏色變化
[模板哈斯克爾](http://www.haskell.org/haskellwiki/Template_Haskell),也許?它甚至比C++中的模板元編程稍微少一些,儘管這並不多。兩者都不是很有趣。 :P –
@ C.A.McCann它可以用於fibs嗎?我的理解是TH更像C宏,但這可能是完全錯誤的。 (也就是說,模板C++是一種剛剛榮耀的宏,嗯,我猜可能在編譯時只通過宏來定義C中的fibs,不知道......)無論如何,具體的例子會有所幫助。 – lobsterism
TH是在編譯時執行的任意Haskell代碼,可以生成語法樹來將定義,表達式或其他代碼拼接到代碼中。 C宏甚至沒有開始比較。它遠不如C++模板垃圾那樣有限,使用任何非平凡的東西都是一種痛苦,因爲使用AST數據類型很笨拙。 –