Home

Awesome

Hey GHC, what-it-do?

what-it-do is a GHC source plugin that rewrites do expressions to trace all binds. For example, given the following code:

main =
  do 
    a <- return ( 42 :: Int )
    b <- return ( a * 2 )
    f <- return ( \b -> return ( b - 1 ) )
    c <- f ( a * b )
    print c

We can trace all binds by using debugDo from what-it-do, and enabling the plugin:

{-# OPTIONS -fplugin=WhatItDo #-}
import WhatItDo (traceDo)
main =
  traceDo (do 
    a <- return 42
    b <- return ( a * 2 )
    f <- return ( \b -> return ( b - 1 ) )
    c <- f ( a * b )
    print c)

Now, when this code runs, we see:

(Test.hs:5:5-29) a = 42
(Test.hs:6:5-25) b = 84
(Test.hs:8:5-20) c = 3527
3527

Magic!

Wha... how is this possible?

Under the hood, what-it-do has rewritten the original do expression to:

main =
  do 
    a <- return ( 42 :: Int ) >>= \x -> trace ( show x ) ( return x )
    b <- return ( a * 2 ) >>= \x -> trace ( show x ) ( return x )
    f <- return ( \b -> return ( b - 1 ) )
    c <- f ( a * b ) >>= \x -> trace ( show x ) ( return x )
    print c

Notice that because the plugin has access to the type-checker, we only trace things that can be shown. The binding to f doesn't get traced, because we can't show what f is.