
Backtracking, Interleaving, and Terminating Monad Transformers (2005) [pdf] - setra
http://okmij.org/ftp/papers/LogicT.pdf
======
danidiaz
These notes explain the logic monad by solving solve n-queens with it:
[https://github.com/sshastry/queenslogic](https://github.com/sshastry/queenslogic)
Despite its name, it's more of a search monad, it doesn't perform unification
or anything like that.

Another interesting paper is "Monad transformers for backtracking search"
[https://arxiv.org/abs/1406.2058](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...](http://hackage.haskell.org/package/transformers-0.5.4.0/docs/Control-
Monad-Trans-Select.html)

~~~
ocharles
Oh neat, I didn't know Ross had actually released a version of transformers
with Select. Now I've _got_ to go learn it.

------
misja111
I like FP and Haskell, but when I read a paper like this and realize the
amount of effort it takes to implement a basic backtracking algorithm, then I
wonder if Haskell can ever become mainstream in production environments.

~~~
mbrock
Do you know of an example of another general backtracking DSL implemented in
another language that is significantly easier or more concise?

~~~
misja111
This is not what my comment is about. You wouldn't normally write a general
backtracking DSL in an imperative language because a backtracking algorithm is
trivial to write.

Only when you are using a pure functional language it becomes non trivial to
combine the results of the individual sub branches.

~~~
setra
Perhaps you misunderstand what this is doing? Or perhaps I misunderstand what
you mean.

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

~~~
misja111
With backtracking you typically have some kind of pruning stragegy. That means
keeping track of your best result so far and dont go into branches where it is
clear that they can never beat your current winner anymore.

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.

~~~
setra
Pruning can be implemented by just not computing a part of a stream based on
some predicate.

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.

