// Earlier versions of this thing had lowercase names such as // lec18A.scala, lec18B.scala. /** The meaning of "with" and other words */ abstract class Lec18 { // We make the class abstract so we can declare types, constants, and // methods without giving them values. // Montague notation // The types of individual objects -- class O(val handle: String) { } object O { def apply(h: String) = new O(h) } // Truth values, the types of sentences -- // We could say "type T = Boolean," but we leave it abstract because // there are other possibilities. See ../code/lec18-T-as Sexp.scala type T // VPs are of type O => T (think of them as needing only // a subject to become a truth value). type VP = O => T // A noun has the same type as a VP. type N = O => T // A noun phrase, however, // is a "predicate of predicates." It must be able to // say things about what the predicate applies to. type NP = (O => T) => T // To distinguish words, which operate at the level of sentences, // from their possibly cognate internal representations, we'll // end the former with "W" and the latter with "I". // We'll also _not_ curry the I-functions // Unary predicate -- type Pred1 = O => T // Binary predicates -- type Pred2 = (O, O) => T // haveI(x,y) means "y is associated with x in some vague way." val haveI: Pred2 val skiI: Pred1 val speciesI: Pred2 val sexI: Pred2 val youngI: Pred1 val slideruleI: Pred1 val bringI: Pred2 val dateI: Pred2 // "goes out with" val humanI: O = O("human") // Home sapiens val aardvarkI: O = O("aardvark") // The animal species val femaleI: O = O("female") val maleI: O = O("male") val sallyI: O = O("sally") val fredI: O = O("fred") // Connectives // Must remain abstract in this class; but see Lec18Boolean, below -- def notI(x: T): T // These take an arbitrary number of arguments -- def orI(x: T*): T def andI(x: T*): T // Falsehood and truth val fI: T = orI() val tI: T = andI() // "only if" val ifI: (T, T) => T = ((t1, t2) => orI(notI(t1), t2)) // Quantifiers -- val forallI: (O => T) => T val existI: (O => T) => T // The "W" entities can actually be defined, whereas the "I" // entities can only be declared (with a few exceptions). (We // should also have axioms, or "meaning postulates," that // circumscribe the meaning somewhat.) def sallyW: NP = ((vp: O =>T) => vp(sallyI)) def fredW: NP = ((vp: O =>T) => vp(fredI)) def girlW: N = ((x: O) => andI(speciesI(x, humanI), sexI(x, femaleI), youngI(x))) def boyW: N = ((x: O) => andI(speciesI(x, humanI), sexI(x, maleI), youngI(x))) def aardvarkW: N = ((x: O) => speciesI(x, aardvarkI)) def slideruleW: N = slideruleI // Useful utility ("combinator"): // ><(x)(y)(z) = y(x)(z) // The name suggests the "flipping" of the normal order // It makes y look like an infix operator even though we can't // define new infixes (with the tools at hand). def ><[A,B](leftArg: A)(f: A => B): B = f(leftArg) // Let's put an uppercase 'L' on a parameter that normally appears // to the left of the function in control of it. // To enhance readability (!), we'll write the semantics // for "boy with a bat" as ><(boyW)(withW)(anW(batW)) instead of // withW(boyW)(anW(batW)) // ><(nBL)(withW)(x) is an nB that has an x def withW(nBL: N)(prepObj: NP): N = ((x: O) => prepObj((y: O) => andI(nBL(x), haveI(x, y)))) // If quantifiers took two curried args (restriction and scope) -- // ((x: O) => prepObj(nBL)(with)(x) // -- adapted from Steedman 1996 _Surface Structure and Interpretation_ // (MIT Press), p. 19 // -- This is "with" Used as an adjunct, not a complement. // We account for the broad and fuzzy meaning of "with" // by reducing it to the broad and fuzzy meaning of "haveI." // In phrases like "girl with a slide rule," "tree with a // a slide rule," we'll just say it combines the meaning // of the noun (more generally, a "noun-bar," written n' by // linguists) with the meaning of "a slide rule" via the // predicate "haveI:" haveI(girl1, slide-rule2), // haveI(tree23, slide-rule2), // and so forth. In this sense, "haveI(x,y)" just means "y is // associated with x in a way dependent on what x is, what y is, // and context (whatever *that* is)." // Syntactic categories of the form "xB" are x-bars, projections // of x that behave like xs. E.g, "nB" means "n[oun]-bar," a // phrase like "girl with a sliderule who studies hard." // Tack a determiner on the front and it becomes a "XP," or // "x phrase," such as an NP. // The L subjectL in broughtW (below) means the // subject will usually appear to the left because it derives from // an NP that's in control of the predicate. So we can literally // write "SallyW(skisW)". def skisW: VP = ((xL: O) => skiI(xL)) // which = skiI // Given the direct-object NP, denotes a predicate. // kissesW(fredW) is the predicate true of anything that kisses fred (same // type as "skisW" type VerbTR = NP => VP // Abstract the straightforward transitive-verb pattern def verbTR(vb: Pred2): VerbTR = // ((dirObj: NP) => dirObj((y: O) => (x: O) => vb(x, y))) ((dirObj: NP) => (x: O) => dirObj((y: O) => vb(x, y))) val broughtW = verbTR(bringI) def datesW = verbTR(dateI) def everyW(nB: O => T): NP = ((vp: O => T) => forallI(x => ifI(nB(x), vp(x)))) def someW(nB: O => T)(vp: O => T): T = existI(x => andI(nB(x), vp(x))) // Pretend "a[n]" means the same as "some," which it // definitely doesn't. (But we have only two quantifiers to // play with at this point.) def anW(nB: O => T)(vp: O => T): T = existI(x => andI(nB(x), vp(x))) // Now we see if all of the following type-check. // Exercise: Change W-functions so they produce as S-expressions // (or some more tailored representation of abstract syntax) the // actual internal representation of a sentence. def lec18S1: T = sallyW(skisW) def lec18S2: T = everyW(girlW)(skisW) // "Every girl with a slide rule skis." def lec18S3: T = everyW(><(girlW)(withW)(anW(slideruleW)))(skisW) // "Some girl dates every boy with an aardvark." def lec18S4: T = someW(girlW)(datesW(everyW(><(boyW)(withW)(anW(aardvarkW))))) // Same thing done in two steps -- // First a noun-bar (N' in linguistics notation) -- def lec18NB1: O => T = ><(boyW)(withW)(anW(aardvarkW)) // Now plug into everyW(...) -- def lec18S4alt: T = someW(girlW)(datesW(everyW(lec18NB1))) // "Every girl brought a boy with a slide rule." def lec18S5: T = everyW(girlW)(broughtW(anW(><(boyW)(withW)(anW(slideruleW)))_)) } /** A subclass of Lec18 in which T = Boolean, not(x) = !x, etc. * Still abstract because we have no way of evaluating, e.g., * skiI(sallyI). That is, we have no inferential procedures * capable of checking on any fact --- and we never will (unless * Google invents them) */ abstract class Lec18Boolean extends Lec18 { type T = Boolean def notI(x: T): T = !x // These take an arbitrary number of arguments -- def orI(x: T*): T = { def disjunctsCheck(dl: List[Boolean]): Boolean = dl match { case Nil => false case d :: ds => if (d) true else disjunctsCheck(ds) } disjunctsCheck(x.toList) } def andI(x: T*): T = { def conjunctsCheck(cl: List[Boolean]): Boolean = cl match { case Nil => true case c :: cs => if (c) conjunctsCheck(cs) else false } conjunctsCheck(x.toList) } }