Debugging
When debugging, it is often helpful to output the value of an expression or variable.
We might try something like:
def sum(x: Int32, y: Int32): Int32 =
let result = x + y;
println("The sum of ${x} and ${y} is ${result}");
result
Unfortunately this does not work:
❌ -- Type Error -------------------------------------------------- Main.flix
>> Unable to unify the effect formulas: 'IO' and 'Pure'.
1 |> def sum(x: Int32, y: Int32): Int32 =
2 |> let result = x + y;
3 |> println("The sum of ${x} and ${y} is ${result}");
4 |> result
The problem is that println has the IO. Hence, we cannot use it to for
print debugging inside pure functions. We could make our sum function have
the IO effect, but that is rarely what we want. Instead, Flix has a
built-in debugging facility that allows us to do print-line debugging.
The Debug.dprintln Function
Instead, we can use the Debug.dprintln function and write:
use Debug.dprintln;
def sum(x: Int32, y: Int32): Int32 =
let result = x + y;
dprintln("The sum of ${x} and ${y} is ${result}");
result
Inside the sum function, the dprintln has the effect Debug, but due to
its special nature, the Debug effect "disappears" once we exit the function,
i.e. it is not part of its type and effect signature.
Debugging with Source Locations
We can use the special debug string interpolator to add source locations to our print statements:
use Debug.dprintln;
def sum(x: Int32, y: Int32): Int32 =
let result = x + y;
dprintln(d"The sum of ${x} and ${y} is ${result}");
result
A longer introduction to
dprintlnis available in the blog post Effect Systems vs Print Debugging: A Pragmatic Solution