0

假设我想写一个打招呼的代码,但出于某种原因,我不想打招呼一个叫 John 的人,我想让 GF 生成这种句子。

抽象版

我知道这种结果可以从抽象文件中实现,例如:GreetingFromAbstract.gf

abstract GreetingFromAbstract = {

  flags startcat = Sentence;

  cat
    Relation;
    Sentence; 
    Verb Relation; 
    Noun Relation;
    


  fun
    MySentence : (rel : Relation) -> Verb rel -> Noun rel -> Sentence;
    Say : Verb RelA;
    Mike : Noun RelA;
    John : Noun RelB;
    RelA, RelB : Relation;
}

具体文件是这样的: GreetingFromAbstractEng.gf

concrete GreetingFromAbstractEng of GreetingFromAbstract = open SyntaxEng, ParadigmsEng, IrregEng, Prelude in {
  lincat
    Sentence = Phr; 
    Verb = V3; 
    Noun = N;
    Relation = {s : Str};


  lin
    MySentence _ action person = sayHi (action) (person);

    Say = mkV3(say_V) (noPrep) (to_Prep);
    Mike = mkN("Mike");
    John = mkN("John");
    RelA, RelB = {s = ""};


  oper
    -- Generate the final sentence
    sayHi : V3 -> N -> Phr =
      \v, n -> mkPhr(mkUtt(mkImp(mkVP
                                  (v)
                                  (mkNP (mkN "hi"))
                                  (mkNP (n)))));
   
  }

但是,假设出于某种原因,我不想从抽象文件而是从具体文件中做到这一点。我希望写名字的人决定向哪个人打招呼,哪个不打招呼。

具体版本

根据我的问题,我写了这段代码:GreetingFromConcrete.gf

abstract GreetingFromConcrete = {

  flags startcat = Sentence;

  cat
    Sentence; Verb; Noun;


  fun

    MySentence : Verb -> Noun -> Sentence;
    Say : Verb;
    Mike : Noun;
    John : Noun;
}

具体:GreetingFromConcreteEng.gf

concrete GreetingFromConcreteEng of GreetingFromConcrete = open SyntaxEng, ParadigmsEng, IrregEng, Prelude in {
  lincat
    Sentence = Phr; 
    Verb = {v : V3 ; rel : Relation}; 
    Noun = {n : N ; rel : Relation};


  lin
    -- MySentence first judge if these two given variables are a good match
    MySentence action person = case <action.rel, person.rel> of {
      <RelA, RelA> => sayHi (action.v) (person.n);
      <RelB, RelB> => sayHi (action.v) (person.n);
      <_, _> => sayHi (action.v) (mkN(nonExist))
      };

    Say = {v = mkV3(say_V) (noPrep) (to_Prep); rel = RelA};
    Mike = {n = mkN("Mike") ; rel = RelA};
    John = {n = mkN("John") ; rel = RelB};


  param
    Relation = RelA | RelB;

  oper
    -- Generate the final sentence
    sayHi : V3 -> N -> Phr =
      \v, n -> mkPhr(mkUtt(mkImp(mkVP
                                  (v)
                                  (mkNP (mkN "hi"))
                                  (mkNP (n)))));
   
  }

问题

我的解决方案显然不是最好的解决方案,因为它会导致在使用 command 时生成 50% 的空句子gr | l,参数越大,情况越糟Relation

问题

1-有没有办法强制抽象只给出具体文件中匹配的参数?
2-或者是否有任何可能的方法要求抽象在与具体不匹配时提供另一个参数,而不是仅使用生成空行nonExist

4

1 回答 1

1

至于你的问题,没有也没有。

GF shell 中更好的工作流程

如果你想在 GF shell 中减少烦人的工作流程,你可以gr一次写几个句子,那么它更有可能得到一些线性化。像这样:

GreetingFromConcrete> gr -number=10 | l 
say hi to Mike
say hi to Mike
say hi to Mike

say hi to Mike




say hi to Mike

要摆脱空行,您可以使用?GF shell 中的管道来传递外部命令:

GreetingFromConcrete> gr -number=10 | l  | ? tr -s '\n'
say hi to Mike
say hi to Mike
say hi to Mike
say hi to Mike
say hi to Mike

删除重复的tr -s字符实例,在这种情况下是换行符,并且输出中不会有空行。

GF 语法中的“过度生成”

您将选择限制任务从抽象语法(依赖类型)转换为具体语法(参数)的方式非常好,这是在 GF 中完成工作的标准方式。我在之前的答案中提出了类似的转换(向下滚动到3. Alternative way of making this grammar withoutdependent types)。

GF 语法通常嵌入到更大的程序中。GF 语法是否过度生成无关紧要——Python/Haskell/... 程序注意只使用想要的树,而不使用不需要的树。我以前在我的博客中写过这个。

于 2021-09-01T01:56:25.103 回答