1
import Debug.Trace

main  :: IO ()
main = do
  let b = (fff 2 10)
  print b
  let c = (fff 3 10)
  print c
  print "---"


ff :: (->) Int Int
ff = do
  x <- traceShow "x is: " . traceShowId
  pure $ (x)

fff :: Int -> Int -> Int
fff = do
  (-) . ff

The trace functions seem to be lazily evaluated or something which means the output can vary from:

"x is: "
2
-8
"x is: "
-7
3
"---"

And in another run:

"x is: "
2
"x is: "
3
-8
-7
"---"

I've tried the suggestions from here: How do I force evaluation of an IO action within `unsafePerformIO`? (BangPatterns Pragma + $!) as well as adding the Strict and StrictData pragmas, however I still get the inconsistent behavior.

{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE Strict #-}
{-# LANGUAGE StrictData #-}

import Debug.Trace

main  :: IO ()
main = do
  let !b = (fff 2 10)
  print b
  let !c = (fff 3 10)
  print c
  print "---"

ff :: (->) Int Int
ff = do
  x <- id $! (traceShow "x is: " . traceShowId)
  pure $ (x)

fff :: Int -> Int -> Int
fff = do
  (-) . ff

I've also tried using unsafePerformIo but this has similar behavior:

hmm :: a -> a
hmm x = unsafePerformIO $! do
  pure x

ff :: Int -> Int
ff z = do
  hmm (trace "x is: " . traceShowId) $ z 

Is there a solution without having to have knowledge about strictness / Haskell's evaluation?

Will Ness
  • 70,110
  • 9
  • 98
  • 181
Chris Stryczynski
  • 30,145
  • 48
  • 175
  • 286

3 Answers3

1

Debug.Trace functions print to stderr so interleaving is to be expected.

At the very least, you could put x and the string before it together to distinguish it from other print output.

ff :: Int -> Int
ff x = trace ("x is: " ++ show x) x

You can also use unsafePerformIO to redefine trace functions that print to stdout to enforce some ordering.

Li-yao Xia
  • 31,896
  • 2
  • 33
  • 56
1

It sounds like you're dealing with buffering issues. You can use hFlush or just set the buffering:

hSetBuffering stderr NoBuffering
hSetBuffering stdout NoBuffering
Thomas M. DuBuisson
  • 64,245
  • 7
  • 109
  • 166
1
myTrace :: Show a => a -> a
myTrace x = unsafePerformIO $ do
  print x
  pure x

The above seems to work well. Thanks to https://stackoverflow.com/users/6863749/li-yao-xia

Chris Stryczynski
  • 30,145
  • 48
  • 175
  • 286