Your problem is the difference between evaluation and execution.
When you write something like:
Console.log "foo"
contrary to your intuition, that does not actually print anything to console. Instead, this creates an "action", which has to be "executed" at some later point, and it's only then that it will print something to the console.
Conversely, same action can actually be "executed" several times, and thus produce multiple effects:
printFoo = Console.log "foo"
-- ^ Nothing is printed at this point
main = do
printFoo
printFoo
printFoo
-- ^ "foo" is printed three times
- "Evaluation" is creating the "action"
- "Execution" is running the "action" in order to produce whatever effects it produces
In the above example, evaluation happens once, but execution - three times.
The way unless
works, it takes a Boolean
value and an "action", and it returns another "action":
dontPrintFoo = unless true printFoo
When you execute the action dontPrintFoo
, it will be the action returned by unless
, which will examine the Boolean
parameter and choose not to execute the action printFoo
.
But say you have a bit more complicated scenario:
dontPrintFoo = unless true $ if qux then printFoo else printBar
Here, both parameters of unless
must be "evaluated" (but not "executed"!) before they are passed to unless
. This means that the value of qux
and the result of if
/then
is calculated before calling unless
. But the resulting action would be executed later, when the whole result is called from main
.
But trace
is special. Magic. Even though it produces an effect (printing to console), the compiler thinks it's a pure function. Like 2 + 3
or like if qux then foo else bar
. It's done this way for debugging convenience: so that you can insert tracing in pure, non-effectful code.
This means that trace
is evaluated at "evaluation" time, not "execution". Which means that it's evaluated before unless
is even called, and therefore it's evaluated regardless of whether the Boolean
parameter is true
or false
.
If you want the tracing to only work when unless
decided to execute the action, try traceM
:
unless (...) do
traceM (show scrollDelta)
foo
bar