@risto: minikanren and microkanren are different beasts in terms of implementation. The stream stuff is specific to microkanren and descendants of it I believe. Minikanren as I understand it is as described/used in the reasoned schemer. microkanren in the reasoned schemer 2nd edition. Also Byrd’s thesis is minikanren / Hemann’s paper microkanren. I’m only just delving into the differences here myself, but I’m not sure programs written for one are always portable to the other… e.g. microkanren skips the occurs check for infinite loops — which might be pertinent to what you’re saying.
I think it’s more or less true that minikanren semantics is what core.logic essentially implements. So if you’re looking at a core.logic appendo
and wondering how it works with reference to the microkanren scheme implementation… I’d first check to see if there is an important difference between how appendo
is written for the two dialects.
It may be the same, but I wouldn’t be surprised if it wasn’t.
ugh...
does anyone know any paper I can read on this or something similar? I can't find anything on this
i don't want to rely on reverse engineering some implementation in case they're doing something weird to make it work, which could end up breaking other abstractions in weird ways
If you’re using core.logic I think you’re probably safest sticking to minikanren literature…. but I have questions about this stuff myself, because i’m not 100% sure either.
core.logic is a minikanren like clojure is a lisp
I still think you are likely encountering a confusion of different levels, and the things you think are calling each other are at different levels of abstraction and not actually calling each other
i'm not confusing different levels of abstraction
i'm working on implementing minikanren
sure, I've done that, I followed the original thesis paper describing it
which seems to be a dead link now 😕
I think this is the best link for that paper now btw: https://github.com/webyrd/dissertation-single-spaced/blob/master/thesis.pdf
Incidentally I can confirm there are differences in appendo between minikanren and microkanren… though they’re pretty close: The reasoned schemer 2nd edition (microkanren) lists it as:
(defrel (appendo l t out)
(conde
((nullo l) (== t out))
((fresh (res)
(fresh (d)
(cdro l d)
(appendo d t res))
(fresh (a)
(caro l a)
(conso a res out))))))
1st edition (minikanren) as:
(define appendo
(lambda (l s out)
(conde
((nullo l) (== s out))
(else
(fresh (a d res)
(caro l a)
(cdro l d)
(appendo d s res)
(conso a res out))))))
(I hand typed those — so there may be errors)
most differences are pretty negligible… main one here seems to be that fresh
in microkanren doesn’t handle multiple bindings at once, and that conde
no longer takes an else
in microkanren
I know you keep saying it isn't a level confusion issue, but I really still think it is, because bind, flatmap, etc are part of the little mini monadic library used for the the lazy streams of results from goals, but they are not actually used in goals themselves
and it has been pretty much a million years since I read the paper, and my implementation was in go, so I didn't bother with any of the list processing library and instead built stuff for using reflection to unify over go records, so I didn't implement appendo or conso
conso, appendo, pretty much anything ending in o is a relation(or function returning a goal), that exists sort of within the domain of minikanren, but bind and flatmap are functions that exist outside of the domain of minikaren and are used to implement it
the papers tend translate the 'o' suffix as a ° (degree symbol) which can make it easy to miss and confuse the names