fun isRelatedTo(a, b, []) = false | isRelatedTo(a, b, (h1, h2)::rest) = (a = h1 andalso b = h2) orelse isRelatedTo(a, b, rest); datatype city = Vancouver | LosAngeles | Mexico | Denver | Omaha | KansasCity | Minneapolis | StLouis | Memphis | NewOrleans | Chicago | Cincinnati | Pittsburgh | Montreal | NewYork; datatype river = Missouri | Platte | NPlatte | SPlatte | Arkansas | Canadian | Kansas | Mississippi | Tennessee | Ohio | Allegheny | Monongahela; datatype Tribe = Asher | Naphtali | Zebulun | Issachar | Dan | Gad | Manasseh | Reuben | Ephraim | Benjamin | Judah | Simeon; datatype WaterBody = Mediterranean | Dead | Jordan | Chinnereth | Arnon | Jabbok; val waterImmedWestOf = [(Mediterranean, Chinnereth), (Mediterranean, Jordan), (Mediterranean, Dead), (Chinnereth, Jabbok), (Chinnereth, Arnon), (Jordan, Jabbok), (Jordan, Arnon), (Dead, Jabbok), (Dead, Arnon)]; val waterWestOf = [(Mediterranean, Chinnereth), (Mediterranean, Jordan), (Mediterranean, Dead), (Mediterranean, Jabbok), (Mediterranean, Arnon), (Chinnereth, Jabbok), (Chinnereth, Arnon), (Jordan, Jabbok), (Jordan, Arnon), (Dead, Jabbok), (Dead, Arnon)]; val flowsInto = [(Platte, Missouri), (Kansas, Missouri),(Missouri, Mississippi), (Canadian, Arkansas), (Arkansas, Mississippi), (Allegheny, Ohio), (Monongahela, Ohio), (Tennessee, Ohio), (Ohio, Mississippi), (NPlatte, Platte), (SPlatte, Platte)]; val isDownstreamFrom = [(Omaha, Denver), (KansasCity, Omaha), (KansasCity, Denver), (StLouis, KansasCity), (StLouis, Omaha), (StLouis, Denver), (StLouis, Minneapolis), (Cincinnati, Pittsburgh), (Memphis, StLouis), (Memphis, KansasCity), (Memphis, Omaha), (Memphis, Denver), (Memphis, Minneapolis), (Memphis, Cincinnati), (Memphis, Pittsburgh), (NewOrleans, Memphis), (NewOrleans, StLouis), (NewOrleans, KansasCity), (NewOrleans, Omaha), (NewOrleans, Denver), (NewOrleans, Minneapolis), (NewOrleans,Cincinnati), (NewOrleans, Pittsburgh)]; val inSameTimeZone = [(Montreal, NewYork), (NewYork, Montreal), (NewYork, Pittsburgh), (Pittsburgh, NewYork), (Montreal, Pittsburgh), (Pittsburgh, Montreal), (Chicago, NewOrleans), (NewOrleans, Chicago), (Chicago, Mexico), (Mexico, Chicago), (NewOrleans, Mexico), (Mexico, NewOrleans), (LosAngeles, Vancouver), (Vancouver, LosAngeles)]; val waterVerticalAlign = [(Chinnereth, Jordan), (Chinnereth, Dead), (Jordan, Chinnereth),(Jordan, Dead), (Dead, Chinnereth), (Dead, Jordan), (Jabbok, Arnon), (Arnon, Jabbok)]; fun testOnePair((a, b), []) = true | testOnePair((a, b), (c, d)::rest) = ((not (b = c)) orelse isRelatedTo(a, d, relation)) andalso testOnePair((a,b), rest); fun test([]) = true | test((a,b)::rest) = testOnePair((a,b), relation) andalso test(rest); fun isTransitive(relation) = let fun testOnePair((a, b), []) = true | testOnePair((a, b), (c, d)::rest) = ((not (b = c)) orelse isRelatedTo(a, d, relation)) andalso testOnePair((a,b), rest); fun test([]) = true | test((a,b)::rest) = testOnePair((a,b), relation) andalso test(rest); in test(relation) end; fun counterTransitive(relation) = let fun testOnePair((a, b), []) = [] | testOnePair((a, b), (c,d)::rest) = (if ((not (b=c)) orelse isRelatedTo(a, d, relation)) then [] else [(a, d)]) @ testOnePair((a,b), rest); fun test([]) = [] | test((a,b)::rest) = testOnePair((a,b), relation) @ test(rest) in test(relation) end; val waterVerticalAlignCorrected = [(Chinnereth, Jordan), (Chinnereth, Dead), (Jordan, Chinnereth),(Jordan, Dead), (Dead, Chinnereth), (Dead, Jordan), (Jabbok, Arnon), (Arnon, Jabbok), (Chinnereth,Chinnereth),(Jordan,Jordan), (Dead,Dead),(Jabbok,Jabbok),(Arnon,Arnon)]; (* Ex 5.6.1, isSymmetric *) fun isSymmetric(relation) = let fun testOnePair((a,b), [] ) = ?? | testOnePair((a,b), (c,d)::rest) = ??; fun test([]) = ?? | test((a,b)::rest) = ?? in test(relation) end; (* Ex 5.6.3, counterSymmetric *) fun counterSymmetric(relation) = let fun testOnePair((a,b), [] ) = ?? | testOnePair((a,b), (c,d)::rest) = ??; fun test([]) = ?? | test((a,b)::rest) = ?? in test(relation) end; val flowsInto = [(Canadian,Arkansas), (NPlatte,Platte), (SPlatte,Platte), (Platte,Missouri), (Kansas,Missouri), (Missouri,Mississippi), (Allegheny,Ohio), (Monongahela,Ohio), (Tennessee,Ohio), (Ohio,Mississippi)]; fun contains(x, []) = false | contains(x, y::rest) = if x = y then true else contains(x, rest); fun makeNoRepeats([]) = [] | makeNoRepeats(x::rest) = if contains(x, rest) then makeNoRepeats(rest) else x::makeNoRepeats(rest); fun transitiveClosure(relation) = relation @ makeNoRepeats(counterTransitive(relation)); fun transitiveClosure(relation) = if isTransitive(relation) then relation else transitiveClosure(makeNoRepeats(counterTransitive(relation)) @ relation); val flowsInto = [(Canadian,Arkansas), (NPlatte,Platte), (SPlatte,Platte), (Platte,Missouri), (Kansas,Missouri), (Missouri,Mississippi), (Allegheny,Ohio), (Monongahela,Ohio), (Tennessee,Ohio), (Ohio,Mississippi)]; fun flowsInto(Canadian, Arkansas) = true | flowsInto(NPlatte, Platte) = true | flowsInto(SPlatte, Platte) = true | flowsInto(Platte, Missouri) = true | flowsInto(Kansas, Missouri) = true | flowsInto(Missouri, Mississippi) = true | flowsInto(Allegheny, Ohio) = true | flowsInto(Monongahela, Ohio) = true | flowsInto(Tennessee, Ohio) = true | flowsInto(Ohio, MIssissippi) = true | flowsInto(x, y) = false; (* Ex 5.7.5; symmetricClosure *) fun symmetricClosure(relation) = ??