我是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数据类型很笨拙。 –