Exercise4-68 <---> Exercise4-70
Exercise 4.69.
Beginning with the data base and the rules you formulated in Exercise4-63, devise a rule for adding greats to a grandson relationship. This should enable the system to deduce that Irad is the great-grandson of Adam, or that Jabal and Jubal are the great-great-great-great-great-grandsons of Adam. (Hint: Represent the fact about Irad, for example, as
((great grandson) Adam Irad)
. Write rules that determine if a list ends in the word grandson. Use this to express a rule that allows one to derive the relationship
((great . ?rel) ?x ?y)
, where ?rel is a list ending in grandson.) Check your rules on queries such as
((great grandson) ?g ?ggs)
and
(?relationship Adam Irad)
.
Ru: Русский текст упражнения
ends-with rule solution (cf last-pair rule on Exercise4-62):
(rule (ends-with ?lis ?x) (last-pair ?lis (?x . ?unused)))
great rule solution:
(rule ((grandson) ?a ?d) (grandson ?a ?d))
(rule ((great . ?rel) ?a ?d)
(and (and (son ?a ?m)
(?rel ?m ?d))
(ends-with ?rel grandson)))Checks:
;;; Query input: ((great grandson) ?g ?ggs) ;;; Query results: ((great grandson) mehujael jubal) ((great grandson) irad lamech) ((great grandson) mehujael jabal) ((great grandson) enoch methushael) ((great grandson) cain mehujael) ((great grandson) adam irad)
;;; Query input: (?relationship Adam Irad) ;;; Query results: ((great grandson) adam irad)
(Haskell notations : Exercise4-63)
Haskell great rule solution :
great rel a d = great' rel a sons d
great' rel a [] d = False
great' rel a (x:xs) d = if a == parent x && rel (name x) d then True else great' rel a xs d
Checks:
[(name d,"great grandson of",parent a)|d<-sons,a<-sons,great grandson (parent a) d]
returns (in ugly-printing) :
[("Irad", "great grandson of","Adam"),
("Mehujael", "great grandson of","Cain"),
("Methushael","great grandson of","Enoch"),
("Lamech", "great grandson of","Irad"),
("Jabal", "great grandson of","Mehujael"),
("Jubal", "great grandson of","Mehujael")]Haskell relationship rule solution :
relationship a d = relationship' "grandson" grandson a d
relationship' display rel a d
| length display > 48 = ("unevaluated", \_ _->False) -- to limit infinite loop when not known relationship
| rel a d = (display,rel)
| otherwise = relationship' ("great ("++display++")") (great rel) a d
note : the value 48 is the length of the string "great (great (great (great (great (grandson)))))" so the first line of the guard is only a trick to choose the end of the recursion
Checks :
ancestor="Adam"
[(name s)++" is a "++(fst r)++" of "++ancestor|s<-sons, let r=relationship ancestor s, snd r ancestor s ]
returns the couples ( stringToDisplay::String, relationship::String->Son->Bool) needed to display :
["Enoch is a grandson of Adam", "Irad is a great (grandson) of Adam", "Mehujael is a great (great (grandson)) of Adam", "Methushael is a great (great (great (grandson))) of Adam", "Lamech is a great (great (great (great (grandson)))) of Adam", "Jabal is a great (great (great (great (great (grandson))))) of Adam", "Jubal is a great (great (great (great (great (grandson))))) of Adam"]
note: the "snd r ancestor s" guard of the call is not very efficient since we have already computed the relationship and we could have sent it via a triple (stringToDisplay, relationship, needToBeDisplayed::Bool). However, working with triples is a little more complicated than working with couples and, in this exercise, the guard is only here to hide
"Cain is a unevaluated of Adam","Jabal is a unevaluated of Adam","Jubal is a unevaluated of Adam"
which would have also appeared without it.
Other solutions goes here (use "#!code haskell", "#!code ocaml", etc. for syntax highlighting)
Exercise4-68 <---> Exercise4-70