Backtracking, Interleaving, and Terminating Monad Transformers (2005) [pdf]
okmij.org
okmij.org
Another interesting paper is "Monad transformers for backtracking search" https://arxiv.org/abs/1406.2058
The Select monad described in the later paper can be found in the "transformers" library http://hackage.haskell.org/package/transformers-0.5.4.0/docs...
And, of course, it's wrapped up in a library anyway, so a lot of the time you won't care.
Only when you are using a pure functional language it becomes non trivial to combine the results of the individual sub branches.
If all you want is to take some kind of search function or backtracking system that generates a stream of results then combining the sub branches is trivial. If you represent a stream as a list and use something like Haskell that is lazy, then all you have to do is literally combine the streams.
myStreamGenerator1 p1 ++ myStreamGenerator2 p2
if you want a different search strategy you can intersperse.
concat . intersperse (mySG1 p1) (mySG2 p2)
the cases being DFS and BFS
So you cannot simply concatenate the results of the subbranches, each new branch needs to be aware of what has been found so far. That can quickly become ugly in pure FP, that's why people have been looking for solutions that do that in an elegant way, e.g. using Monads.
If you want some kind of global state of the current results then you just pass around the current calculated states. Pure FP has many simple solutions for passing around state.
Prolog uses backtracking as the principal control flow paradigm and allows user-defined languages/DSLs by defining tokens, their associativity and precedence in operator-precedence parsing, where tokens are character sequences that are either all graphic characters or all letters/digits.
Example from the book Adventures in Prolog as returned by a cursory Google search:
? op(35, xfx, is_in)
banana is_in room(kitchen)."Building a backtracking facility in smalltalk without kernel support"[1]
Languages like Snobol, Prolog, and Icon were designed with backtracking facilities from the outset and these facilities are deeply intertwined with the implementation. Retrofitting a backtracking facility in a language that wasn't designed for it has never been achieved. We report on an experiment to retrofit Smalltalk with a backtracking facility. The facility is provided through a small number of primitives written in the language (no modifications to the kernel were made). The ability to do this is a direct result of the power provided by the objectification of contexts.
I'll leave the qualitative analysis of which is easier or more concise to others.
[1] http://dl.acm.org/citation.cfm?doid=62084.62094&CFID=7393283...