Monday, November 03, 2014

Breakpoints in monadic code

I was trying to get my autoindenting parser working again in my old monadic F# code under Xamarin. To note that breakpoints are still an issue with higher order code. This post presents a simple way I get around the problem.

The problem is that higher order code, is first run to be assembled as higher order constructions, and then only later run "to do something". For example, monads are first bound, and then "run". The problem is that a breakpoint sets a stop during this construction phase, not during the execution phase. That is reasonable as the construction is what the top level function does, but it is of little use to the developer who wants to break the execution of the code and not its construction.

My parser monad is very combinatorial. I have operators for the classical parsing constructions like "and" and "or", but also a bunch of helper operators that are multiple variations of the bind operator, (e.g. combine two monads, return value of first), as well as error management helpers, and as well as monadic y-combinators to bootstrap recursive structures. When I use these, I rarely need to define functions on the fly, and therefore I end up with very few or even no anchor points for breakpoints.

To help with setting breakpoints, I have two functions both with the signature m<'a>->('a->'a)->m<'a> (give it a monad and a function and it  returns a monad). I define these as operators %>> and >>%. They are a form of restricted map function, the first calls the function before the execution of the monad, the second calls the function  after the execution of the monad. To use these, I define special breakpoint functions, for example "let breakHere x = x , on which I set breakpoints and which I slip in to my code, for example ... (m %>> breakHere) ... will break before the monad m.

This method needs a rebuild to set a new breakpoint. That does restrict its usage, but it is still very helpful.   

No comments: