2

I've tried to come up with ways to break sharing of top level constants in haskell, but so far none of them worked:

module Main where

import Debug.Trace

x1 :: Int
x1 = trace "Eval1" $ 10 + 10

x2 :: () -> Int
x2 = \() -> trace "Eval2" $ 10 + 10

x3 :: () -> Int
x3 () = trace "Eval3" $ 10 + 10

x4 :: () -> Int
x4 () = v
  where v = trace "Eval4" $ 10 + 10

x5 :: () -> Int
x5 = \() -> v
  where v = trace "Eval5" $ 10 + 10

x6 :: () -> Int
x6 () = let v = trace "Eval6" $ 10 + 10 in v

x7 :: () -> Int
x7 = let v = trace "Eval7" $ 10 + 10 in \() -> v

x8 :: () -> Int
x8 = \() -> let v = trace "Eval8" $ 10 + 10 in v


f :: Int -> Int -> Int
f y z = y + z

main :: IO ()
main = do 
  putStrLn "Start"

  print (f x1 3)
  print (f x1 4)

  print (f (x2 ()) 3)
  print (f (x2 ()) 4)

  print (f (x3 ()) 3)
  print (f (x3 ()) 4)

  print (f (x4 ()) 3)
  print (f (x4 ()) 4)

  print (f (x5 ()) 3)
  print (f (x5 ()) 4)

  print (f (x6 ()) 3)
  print (f (x6 ()) 4)

  print (f (x7 ()) 3)
  print (f (x7 ()) 4)

  print (f (x8 ()) 3)
  print (f (x8 ()) 4)

I've found that it breaks the sharing when I put {-# INLINE#-} pragmas on the definitions (then it works for all of them).

So my question is: Is there another way to break the sharing of a top level constant in haskell with GHC that doesn't involve INLINE pragmas? Is it guarranted that putting INLINE pragmas breaks the sharing, even for bigger definitions? If not, is there a guarranted way?

Why do I need this? For example, when I write a benchmark, I have a tree structure that is traversed. This structure should not be shared between runs of the benchmark, because building it is part of the benchmark.

bennofs
  • 11,873
  • 1
  • 38
  • 62
  • 1
    This works for me: x9 n = trace "Eval9" $ 10 + 10 + n - n – Jake McArthur Feb 19 '14 at 22:05
  • If you're building the structure as part of the benchmark, how/why is it a top-level constant? Or, if it's truly a constant, why include the setup cost in your benchmark (since it should be identical in all cases)? – John L Feb 19 '14 at 23:24
  • Hmm, right, I hadn't thought about that. I'd still be interrested in answers to the question, of course :) – bennofs Feb 19 '14 at 23:35
  • What's the reason for the downvote? – bennofs May 05 '14 at 18:09

1 Answers1

3

I got your example to avoid sharing with -O2 -fno-full-laziness -fno-cse. I doubt that's sufficient in general, but give it a go for your particular application.

(Note x1 or x5 are shared even with no optimizations on, as their structure explicitly shares the computation).

Tom Ellis
  • 9,224
  • 1
  • 29
  • 54
  • If I put an INLINE pragma on x1, even x1 is shared – bennofs Feb 19 '14 at 20:50
  • You mean "even x1 is *not* shared". Ha, yes, that's true. I guess I meant there's no *optimization* that forces `x1` and `x5` to be not shared, but firstly I suppose you could consider INLINE an optimization and secondly there could theoretically be an "optimization" which removes their sharing. I'll adjust my claim. – Tom Ellis Feb 19 '14 at 20:55