I've been working through "Prolog and Natural Language Analysis" in
miniKanren recently https://github.com/tca/PANL/ (link to book in README).
It covers all the things you need to make a program like this, and it
chapter 5 it has you make one.
The key thing you are missing is building the logical forms of the
sentences so you can pull out the parts you want.
I wrote up very simple dialogue program that works based on extracting
relation tuples from the logical forms. A statement will add the tuple to
the database; a question will put variables in the tuple and query the
database with it. There is obviously a lot more to do but it's a start!
(use-modules (minikanren language)
(minikanren dcg))
(use-modules (ice-9 readline))
(--> (question s)
(fresh (np vp s1)
(conde ((wh-question np) (verb-phrase `(lambda (,np) ,s)) '(?)))))
(--> (statement s)
(fresh (np vp s1)
(conde ((noun-phrase np) (verb-phrase `(lambda (,np) ,s))))))
(--> (verb-phrase vp)
(fresh (tv np)
(conde ((transitive-verb `(lambda (,np) ,vp)) (noun-phrase np))
((intransitive-verb vp)))))
(--> (transitive-verb logical-form)
(fresh (tv)
(conde (`(,tv) (escape (transitive-verbo tv logical-form))))))
(define (transitive-verbo tv logical-form)
(fresh (x y)
(conde ((== tv 'wrote))
((== tv 'played)))
(== logical-form `(lambda (,x) (lambda (,y) (,tv ,x ,y))))))
(--> (intransitive-verb exp)
(fresh (x)
(conde ((== exp `(lambda (,x) (halts ,x)))
'(halts)))))
(--> (noun-phrase x)
(fresh (d x^)
(conde ((proper-noun x))
((== x `(,d ,x^)) (determiner d) (noun x^)))))
(--> (determiner x)
(conde ((== x 'the) '(the))))
(--> (proper-noun logical-form)
(fresh (pn)
(conde (`(,pn) (escape (proper-nouno pn logical-form))))))
(define (proper-nouno pn logical-form)
(fresh ()
(== pn logical-form)
(conde
((== pn 'will))
((== pn 'jason))
((== pn 'dan))
((== pn 'oleg))
((== pn 'kanren))
((== pn 'minikanren))
((== pn 'microkanren)))))
(--> (noun n)
(conde ((== n 'cat) '(cat))
((== n 'guitar) '(guitar))))
(--> (wh-question x)
(fresh (x)
(conde ((== x 'who) `(,x)))))
(define (membero x l)
(fresh (head tail)
(== l `(,head . ,tail))
(conde
((== x head))
((membero x tail)))))
(define (query in db db^ out)
(fresh (logical-form)
(conde
((statement logical-form in '())
(== db^ (cons logical-form db))
(== out 'ok!))
((question logical-form in '())
(== db db^)
(membero logical-form db)
(statement logical-form out '())))))
(define db '())
(define (run-query in)
(let ((answer (run^ 1 (lambda (state)
(fresh (db^ out)
(== state (cons db^ out))
(query in db db^ out))))))
(if (null? answer)
(display "I don't know.")
(let ((state (caar answer)))
(let ((db^ (car state))
(out (cdr state)))
(set! db db^)
(display out)))))
(newline))
(define (dialogue)
(call-with-input-string (string-append "(" (readline "> ") ")")
(lambda (in) (run-query (read in))))
(dialogue))
(dialogue)
;; > will wrote minikanren
;; ok!
;; > jason wrote microkanren
;; ok!
;; > oleg wrote kanren
;; ok!
;; > the cat played the guitar
;; ok!
;; > dan played will
;; ok!
;; > who played the guitar ?
;; (the cat played the guitar)
;; > who played will ?
;; (dan played will)
;; > who wrote kanren ?
;; (oleg wrote kanren)
;; > who wrote minikanren ?
;; (will wrote minikanren)
;; > who wrote microkanren ?
;; (jason wrote microkanren)
;; > who halts ?
;; (minikanren halts)
--
You received this message because you are subscribed to the Google Groups
"minikanren" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/minikanren.
For more options, visit https://groups.google.com/d/optout.