diff --git a/doc/tutorial/gf-tutorial2.html b/doc/tutorial/gf-tutorial2.html index cc3f6f3d8..22cf7a38e 100644 --- a/doc/tutorial/gf-tutorial2.html +++ b/doc/tutorial/gf-tutorial2.html @@ -732,12 +732,249 @@ The graph uses -
+ the boy eats two snakes + all boys sleep ++The new grammatical facility we need are the plural forms +of nouns and verbs (boys, sleep), as opposed to their +singular forms.
+The introduction of plural forms requires two things: +
+ +To be able to do all this, we need a couple of new judgement forms, +a new module form, and a more powerful way of expressing linearization +rules. + + + +
+ param Number = Sg | Pl ; ++To express that nouns in English have a linearization +depending on number, we replace the linearization type {s : Str} +with a type where the s field is a table depending on number: +
+ lincat CN = {s : Number => Str} ;
+
+The table type Number => Str is in many respects similar to
+a function type (Number -> Str). The main restriction is that the
+argument type of a table type must always be a parameter type. This means
+that the argument-value pairs can be listed in a finite table. The following
+example shows such a table:
+
+ lin Boy = {s = table {
+ Sg => "boy" ;
+ Pl => "boys"
+ }
+ } ;
+
+The application of a table to a parameter is done by the selection
+operator !. For instance,
++ Boy.s ! Pl ++is a selection, whose value is "boys". + + + +
+ +From GF point of view, a paradigm is a function that takes a lemma - +a string also known as a dictionary form - and returns an inflection +table of desired type. Paradigms are not functions in the sense of the +fun judgements of abstract syntax (which operate on trees and not +on strings). Thus we call them operations for the sake of clarity, +introduce one one form of judgement, with the keyword oper. As an +example, the following operation defines the regular noun paradigm of English: +
+ oper regNoun : Str -> {s : Number => Str} = \x -> {
+ s = table {
+ Sg => x ;
+ Pl => x + "s"
+ }
+ } ;
+
+Thus an oper judgement includes the name of the defined operation,
+its type, and an expression defining it. As for the syntax of the defining
+expression, notice the lambda abstraction form \x -> t of
+the function, and the glueing operator + telling that
+the string held in the variable x and the ending "s"
+are written together to form one token.
+
+
+
++ +The resource module type thus consists of +param and oper definitions. Here is an +example. +
+ resource MorphoEng = {
+ param
+ Number = Sg | Pl ;
+ oper
+ Noun : Type = {s : Number => Str} ;
+ regNoun : Str -> Noun = \x -> {
+ s = table {
+ Sg => x ;
+ Pl => x + "s"
+ }
+ } ;
+ }
+
+Resource modules can extend other resource modules, in the
+same way as modules of other types can extend modules of the
+same type.
+
+
+
+
+
+concrete PaleolithicEng of Paleolithic = open MorphoEng in {
+ lincat
+ CN = Noun ;
+ lin
+ Boy = regNoun "boy" ;
+ Snake = regNoun "snake" ;
+ Worm = regNoun "worm" ;
+ }
+
+Notice that, just like in abstract syntax, function application
+is written by juxtaposition of the function and the argument.
+
++ +Using operations defined in resource modules is clearly a concise +way of giving e.g. inflection tables and other repeated patterns +of expression. In addition, it enables a new kind of modularity +and division of labour in grammar writing: grammarians familiar with +the linguistic details of a language can put this knowledge +available through resource grammars, whose users only need +to pick the right operations and not to know their implementation +details. + + + + +
+ oper mkNoun : Str -> Str -> Noun = \x,y -> {
+ s = table {
+ Sg => x ;
+ Pl => y
+ }
+ } ;
+
+Thus we define
++ lin Louse = mkNoun "louse" "lice" ; ++instead of writing the inflection table explicitly. + +
+ +The grammar engineering advantage of worst-case macros is that +the author of the resource module may change the definitions of +Noun and mkNoun, and still retain the +interface (i.e. the system of type signatures) that makes it +correct to use these functions in concrete modules. In programming +terms, Noun is then treated as an abstract datatype. + + + + +
+ regNoun : Str -> Noun = \snake -> mkNoun snake (snake + "s") ; + sNoun : Str -> Noun = \kiss -> mkNoun kiss (kiss + "es") ; ++What about nouns like fly, with the plural flies? The already +available solution is to use the so-called "technical stem" fl as +argument, and define +
+ yNoun : Str -> Noun = \fl -> mkNoun (fl + "y") (fl + "ies") ; ++But this paradigm would be very unintuitive to use, because the "technical stem" +is not even an existing form of the word. A better solution is to use +the string operator init, which returns the initial segment (i.e. +all characters but the last) of a string: +
+ yNoun : Str -> Noun = \fly -> mkNoun fly (init fly + "ies") ; ++The operator init belongs to a set of operations in the +resource module Prelude, which therefore has to be +opened so that init can be used. + + + + +