Haskell template metaprogramming option

I am new to Haskell. Given Haskell’s entire premise, the function will always return the same value, I expect some way, for example, by calculating the values ​​of the Fibonacci constants at compile time, as I can do in C ++ with the metaprogrmming pattern, but I don’t see , how to do it. Is there any way?

+4
source share
2 answers

edit: Daniel Fisher points out that you can raise a regular expression in Template Haskell and evaluate the result at compile time taking into account certain restrictions on the type of output using the regular fib function, and then splicing

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

The following is the original answer.

As pointed out in the comments, Template Haskell is the way to go about it. For inductive functions such as fibonacci, it is quite simple. You write code similar to the standard definition, but returning an ExpQ value. Due to splicing restrictions, you will need to use 2 modules.

 {-# 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)) |] 

and

 {-# LANGUAGE TemplateHaskell #-} module Main where import TH y :: Int y = $(fibTH 10) main = print y 

To confirm that the work is done at compile time, we can compile with -ddump-simpl to see the kernel that confirms it.

 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 
+9
source

There is an excellent article by Don Stewart, where he shows that using the LLVM backend with the correct flag selection will precompute certain functions at compile time and replace them with constants.

+5
source

All Articles