Reputation: 1069
I'm a Haskell newbie and I want to do something which has a side effect like this:
i = 3.0
main :: IO ()
main = let m = print i in putStrLn "Hello world"
Then I can know the value of i
when main
runs, but the I
didn't print. I add !
before m
but it also doesn't work. I would like to know how to hack this, thanks in advance!
Upvotes: 4
Views: 3603
Reputation: 55069
In an IO
action, you can just use putStrLn
or print
as usual, like
do
print i
putStrLn "Hello world"
Which desugars to print i >> putStrLn "…"
. This is equivalent, but not really any better because the action m
doesn’t really need to be named:
let m = print i -- define an action
in do
m -- ensure the action is actually executed
putStrLn "Hello world"
In a pure function, you can use trace
or traceShow
from Debug.Trace
:
traceShow i (putStrLn "Hello world")
But be aware that these print when the expression is forced, which may be in a different order than you may expect due to lazy evaluation, or not at all if a value is never used. You can add strictness annotations with seq
or BangPatterns
as you tried for the monadic code to assist with making sure that things are forced when you expect—the reason !m = …
didn’t work for your IO
action is that the strictness annotation only makes the expression evaluated, producing an IO
action but not executing it because it’s not sequenced with another action as part of main
. Remember: you can only (purely) construct IO
actions and bind them together; the runtime is what actually executes them.
Finally, in a “pure” monad where you don’t have IO
available, you can still use trace
&c., for example in the list monad:
numbers :: [Int]
numbers = do
x <- [1, 2, 3]
traceShow x (pure ())
y <- [4, 5, 6]
traceShow y (pure ())
pure (x * y)
Upvotes: 4
Reputation: 120079
For debugging, use trace
and friends.
import Debug.Trace
i = 3.0
main :: IO ()
main = traceShow i $ putStrLn "Hello world"
Note the trace appears on the standard error stream, as debugging output should.
The function you use trace
in doesn't have to be IO-typed. This for example will also work:
add a b = a + traceShow i b
Trace functions are a bit foreign to Haskell because they are technically impure. However the side effects are limited in scope and not observable by the program itself, so it's kinda OK.
Upvotes: 5
Reputation: 20542
You created m
but never used it. To fix that you can try:
i = 3.0
main :: IO ()
main = let m = print i in m >> putStrLn "Hello world"
Upvotes: 3