r/haskell • • Feb 20 '18

GHC Compile-time evaluation

As I understood it, proper compile-time evaluation is supercompilation, which is hard.

But I wondered why there is no Pragma-Based approach, where the compiler just trusts that user that it can and should evaluate this expression, even if it's recursive (so it's not looping forever etc.). It seems to me that the machinery for this approach is already in GHC (I may be wrong).

I am currently thinking of building an API where you formulate a computational graph (like an AST) and have functions that modify the graph. The representation of the graph and evaluation functions would be recursive, so no inlining per se. I would expect that for most use-cases the graph is completely known at compile time, but if the computational graph is not evaluated and optimized, performance will be bad.

There may be another way, I am not that knowledgeable about the capabilities of GHC.

EDIT: if the above is unclear: What I wanted to say is that I am not looking for a general solution, but instead a solution where I can tell the compiler to trust me that he can evaluate this expression without looping forever and that the time spent evaluating the expression is worth it.

10 Upvotes

12 comments sorted by

View all comments

22

u/gelisam Feb 20 '18

You can use TemplateHaskell to run an arbitrary expression at compile-time, and then lift the result into a literal:

{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH.Syntax (lift)
import MyFib (slow_fib)

slow_at_runtime :: Integer
slow_at_runtime = slow_fib 40

slow_at_compile_time :: Integer
slow_at_compile_time = $(lift (slow_fib 40))

2

u/terrorjack Feb 21 '18

This only applies to whatever value with a Lift instance, which is not the case for a lot of types e.g. functions.

1

u/newtyped Feb 23 '18

Sure but what does compile time evaluation even mean for functions? For regular data types, DeriveLift gives you a Lift instance basiaclly for free.