我是Haskell的新手。鉴于Haskell的整个前提是一个函数总是会返回相同的值,我希望有一些方法,例如在编译时计算常量的fibonacci值,就像我可以在C ++中使用模板元编程一样,但我看不出怎么做。有办法吗?
答案 0 :(得分:9)
编辑:Daniel Fischer指出你可以将普通表达式提升到Template 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
答案 1 :(得分:5)
Don Stewart有一个great article,他表示使用带有正确选择标志的LLVM后端将在编译时预先计算某些函数,并用常量替换它们。