I began studying some minikanren and made up this example for counting 1-bits in a list.
(define (count xs n)
(conde
[(== xs '()) (== n 0)]
[(fresh (a b)
(== xs (cons a b))
(conde
[(== a 0) (count b n)]
[(== a 1) (count b (- n 1))]))]))
Now the following works fine
> (run* (q) (fresh (a b c) (== q (list a b c)) (count q 1)))
'((0 0 1) (1 0 0) (0 1 0))
but if I change the order of the goals the program does not terminate
> (run* (q) (fresh (a b c) (count q 1) (== q (list a b c))))
. . user break
This is already something that I don't completely understand, does the order of goals matter? In which ways? I think I understood that even the subsequent goals can pose sufficient constraints so as to terminate the search, but of course I must have missed something.
Exploring more of this problem I saw that
> (run 3 (q) (fresh (a b c) (count q 1) (== q (list a b c))))
'((0 0 1) (0 1 0) (1 0 0))
> (run 4 (q) (fresh (a b c) (count q 1) (== q (list a b c))))
. . user break
so I know that it tries to look for more answers than existing. My suspect now is that when the subgoal
(== xs (cons a b))
splits the list there aren't sufficient constraints on b
to make the search finite, which sounds reasonable given that nothing talks about the tail of the list besides the external (== q (list a b c))
. It seems even more reasonable to expect a non termination as nothing says what c
is in (== q (list a b c))
, it may be another list (is it true?), but so how does the swapped version of the program terminate?
I therefore tried
(define (bit x)
(conde [(== x 0)] [(== x 1)]))
and
> (run 4 (q) (fresh (a b c) (bit a) (bit b) (bit c) (count q 1) (== q (list a b c))))
. . user break
but it still does not terminate, so maybe the problem is not that which I thought.
Overall there must be something that I'm missing in my understanding, can anyone clarify all this and point out what would be a correct way of doing this thing?