Showing posts with label template. Show all posts
Showing posts with label template. Show all posts

Thursday, April 17, 2008

Niffy Template Haskell trick for better trace

This trick is by EvilTerran from #haskell freenode IRC channel.

A quick and dirty way to debug Haskell code is to use trace function from Debug.Trace module.

For example,

f (trace ("arg1: " ++ show arg1) arg1) arg2

would print

arg1: <actual value of arg1>

Usung Template Haskell, above code can be shortened.

> {-# LANGUAGE TemplateHaskell #-}

This means this code uses TemplateHaskell extension.

> module Trace where

Let's call the module Trace.

> import Language.Haskell.TH
> import Debug.Trace (trace)

And, import some modules.

> t name = [| trace ($(litE . StringL $ nameBase name)
>    ++ ": " ++ show $(varE name)) $(varE name) |]

Then, define the macro t that can be called as:

$(t 'varName)

And it'll be expanded to:

trace ("varName" ++ ": " ++ show varName) varName

Let's actually use Trace.t in Main module.

> {-# LANGUAGE TemplateHaskell #-}

Main module also needs to use TemplateHaskell extension because it'll include macro call like $(t 'a).

> module Main where
> import Trace (t)
> import Debug.Trace (trace)

> main = do
>     let a = 2
>     let bravo = 40
>     putStrLn $ show ((trace ("a: " ++ show a) a) + bravo)

compare this with

>     putStrLn $ show ($(t 'bravo) + $(t 'a))

>     return ()

Shorter.

Now, I need vim keyboard shortcut that'll replace the word under cursor with $(t 'wordUnderCuror). And, another keyboard shortcut that'll turn $(t 'word) into word.

Edit: Alok commented with vim function below:

" word <===> $(t 'word)
" by Alok
function! ToggleTrace()
    call searchpos('\|)')
    let b = searchpos('\<', 'b')
    let s = searchpos("\$(t '", 'b')
    if s[0] == b[0] && b[1] - s[1] == len("$(t '")
        " remove trace
        norm df'f)x
    else
        " add trace
        call insert (b, 0, 0)
        call add (b, 0)
        call setpos('.', b)
        let @z = "$(t '"
        norm "zP
        let @z = ")"
        norm f "zP
    endif
endfunction

nmap <leader>t :call ToggleTrace()<cr>

Thank you Alok.