Reasoned Schemer (78) caro、cdro、conso
リストの操作
まずはcaro
> (defrel (caro p a) (fresh (d) (== (cons a d) p)))
> (run* q (caro '(a c o r n) q))
'(a)
なんでcons
が理解できるんだろうと思ってたけどunify
とかがリストを前提とした作りになってるからだな
ていうかむしろリストしか知らない
たとえばvectorもunifyできるようにしようと思ったらunify
を拡張しないといけないんだろうな
やっていく
> (run-goal #f (caro '(a c o r n) q))
'(((#(d) c o r n) (#(q) . a)))
そういうstreamができるのか
なるほど
((caro '(a c o r n) q) empty-s)
= ((fresh (d) (== (cons q d) '(a c o r n))) empty-s)
= ((fresh (d) (== `(,q . ,d) '(a c o r n))) empty-s)
= ((call/fresh 'd (lambda (d) (== `(,q . ,d) '(a c o r n)))) empty-s)
= (((lambda (d) (== `(,q . ,d) '(a c o r n))) (var 'd)) empty-s)
= ((== `(,q . ,d) '(a c o r n)) empty-s)
= `((,d c o r n) (,q . a)))
そういえばfresh
からcall/fresh
のあたりどうなってんだっけと思って
書いてみたところ(var 'd)
がいい感じに書けずに少々ゴマかした感がある
結局もとに戻る感じなんだけどどう書くとすんなりするの
それはそれとして(cons a d)
が実は'(#(q) . #(d))
だったりすることがわかってれば
普通にunifyできて不思議はない
cdro
も同じ
> (defrel (cdro p d) (fresh (a) (== (cons a d) p)))
> (run* r (fresh (v) (cdro '(a c o r n) v) (fresh (w) (cdro v w) (caro w r))))
'(o)
いきなりunnestしてる例でややこしい
これはどんなstreamができているのか
> ((fresh (v) (cdro '(a c o r n) v) (fresh (w) (cdro v w) (caro w r))) empty-s)
'(((#(d) r n)
(#(r) . o)
(#(w) o r n)
(#(a) . c)
(#(v) c o r n)
(#(a) . a)))
defrel
を普通の定義に戻すと・・・?
> ((fresh (v) (cdro '(a c o r n) v) (fresh (w) (cdro v w) (caro w r))) empty-s)
#<procedure:...r/minikanren.rkt:76:10>
> (((((fresh (v) (cdro '(a c o r n) v) (fresh (w) (cdro v w) (caro w r))) empty-s))))
'(((#(d) r n)
(#(r) . o)
(#(w) o r n)
(#(a) . c)
(#(v) c o r n)
(#(a) . a)))
forceしていけば同じstreamができる
disj2
があれば順番が変わってきそうな気がする
conso
> (defrel (conso a d p) (caro p a) (cdro p d))
> (run* l (conso '(abc) '(d e) l))
'(((abc) d e))
> (run* x (conso x '(a b c) '(d a b c)))
'(d)
こっちの定義でも同じ
> (defrel (conso a d p) (== `(,a . ,d) p))
> (run* l (conso '(abc) '(d e) l))
'(((abc) d e))
> (run* x (conso x '(a b c) '(d a b c)))
'(d)
むしろこっちの定義をもとにしてcaro
、cdro
を定義するのでは
こうして
(defrel (caro p a) (fresh (d) (conso a d p)))
(defrel (cdro p d) (fresh (a) (conso a d p)))
こう
> (run* q (caro '(a c o r n) q))
'(a)
> (run* r (fresh (v) (cdro '(a c o r n) v) (fresh (w) (cdro v w) (caro w r))))
'(o)
って後で出てきてたわ
完全に忘れてた