在 GF 中扩展限定词 Det 有变量 Gender – 不是固有的如何处理 Case如何实际修复 somePl_Det

问题描述

我之前问过一个关于扩展 which_RP 记录的问题,并将此问题 here 下的关系从句 "that" 更改为 "which"

最近我开始研究意大利语,每当我使用 someSg_DetsomePl_Det 函数时,我都会分别得到以下结果。

qualche albero
qualche alberi

根据我对意大利语的了解,我知道对于单名词 qualche albero 是正确的,但是对于复数名词,我们必须根据名词的性别使用 alcunealcuni .因此,我尝试将函数 somePl_Det 扩展到 somePlM_DetsomePlF_Det,如下所示:

   somePlM_Det : Str -> Det =
        \str ->
             somePl_Det ** {s = table {_ => "alcuni"}};
   somePlF_Det : Str -> Det =
        \str ->
             somePl_Det ** {s = table {_ => "alcune"}};

但是GF编译器一直报这个错误

Happend in operation somePlM_Det
   type of "alcuni"
   Expected: DiffIta.Case => Str;
   inferred: Str;
Happend in operation somePlF_Det
   type of "alcune"
   Expected: DiffIta.Case => Str;
   inferred: Str;

扩展缺少变量DiffIta.Case搜索后,我发现参数 Case 位于文件 DiffRomance.gf 中。尽管我找到了 DiffRomance.Case 但我仍然无法扩展这个功能

请您解释一下DiffRomance.Case用法以及扩展此功能的正确方法是什么。谢谢~

解决方法

只是为了让任何阅读此答案而不是前一个答案的人都清楚:

someWord ** {s = "some string"} 是一个 hack,当 RGL 更新时,不能保证它会起作用。

我确实建议 hack,因为它可能很有用:有时 RGL 不会准确输出您想要它做什么,但这并不是真正应该在上游修复的错误。然后你可以在你的应用程序语法中本地覆盖一些 RGL 定义,但你应该意识到潜在的不稳定性。

现在来回答这个问题。

意大利语 RGL 中 Det 的 Lincat

您正在尝试这样做:

somePlM_Det : Str -> Det =
     \str ->
          somePl_Det ** {s = table {_ => "alcuni"}};

您正尝试将 table {_ => "alcuni"} 插入意大利语 Det 的 s 字段中。让我们看看 here 实际的 lincat 是什么:

    Det     = {
      s : Gender => Case => Str ;
      n : Number ;
      s2 : Str ;            -- -ci
      sp : Gender => Case => Str ;   -- substantival: mien,mienne
      isNeg : Bool -- negative element,e.g. aucun
      } ;

注意类型为 sGender => Case => Str 字段。这是两个嵌套列表,而您试图只给它一个列表。

这行得通,但没有意义:

   somePlF_Det : Str -> Det =
        \str ->
             somePl_Det ** {s = table {_ => table {_ => "alcune"}}};

这有什么问题?两件事,解释如下。

Det 有变量 Gender – 不是固有的

在 RGL 中,那些有性别或其他名词类的语言,通常设计如下。

名词(以及通过继承 CNNP)具有固有的性别。这意味着他们的 lincat 看起来像这样:

lincat 
  N = {s : Whatever => Str ; g : Gender} ;

相反,名词(等)的所有修饰语和量词都有可变性。所以他们的 lincat 看起来像这样:

lincat 
  Det,Quant,A,AP,RS ... = {s : Gender => Whatever => Str} ;

性别在屈折表的左侧,这意味着修饰符/量词的输出取决于其最终头部的性别。名词(或 CN,或 NP)将是中心词,我们将使用中心词的固有性别从修饰语/量词中选择正确的性别。 GF 代码如下所示:

-- In the abstract syntax
fun
  Modify : Modifier -> Head -> Head ;

-- In the concrete syntax (different file)
lin
  Modify mod head = {
    s = \\x => mod.s ! head.g ! x ++ head.s ! x
    } ;

我们使用 head.gmod.s 中选择字符串。变量 x 可以表示任何其他屈折特征,例如大小写或数字---对于本示例无关紧要。

因此定义 somePlM_DetsomePlF_Det 没有意义。我们只想将一个 somePl_Det 应用到任何 CN 中,CN 决定 Det 将输出 alcune 还是 alcuni。>

如何处理 Case

另一个错误的做法是用单个字符串“alcune”或“alcuni”替换屈折表的每个分支。这些案例(和性别)实际上做了一些事情。让我们看看其他一些不需要修复的Det的表。

我在目录 gf-rgl/src/italian 中并打开 GF shell。 (以 > 为前缀的命令是在 GF shell 内完成的。我使用标志 -retain -no-pmcfg 因为意大利 RG 太慢了,这使它更快。)

$ gf 
> i -retain -no-pmcfg LangIta.gf
> cc -unqual -table many_Det
s . Masc => Nom => molti
s . Masc => Acc => molti
s . Masc => CPrep P_di => di molti
s . Masc => CPrep P_a => a molti
s . Masc => CPrep P_da => da molti
s . Masc => CPrep P_in => in molti
s . Masc => CPrep P_su => su molti
s . Masc => CPrep P_con => con molti
s . Fem => Nom => molte
s . Fem => Acc => molte
s . Fem => CPrep P_di => di molte
s . Fem => CPrep P_a => a molte
s . Fem => CPrep P_da => da molte
s . Fem => CPrep P_in => in molte
s . Fem => CPrep P_su => su molte
s . Fem => CPrep P_con => con molte

所有这些介词都是屈折表的一部分!如果你想知道为什么,那是因为这些介词与冠词合并。首先,它们不合并的示例:

> cc -one PrepNP in_Prep (DetCN many_Det (UseN house_N))
in molte case

> cc -one PrepNP with_Prep (DetCN many_Det (UseN cat_N))
con molti gatti

有了这些,它们就会合并。

> cc -one PrepNP in_Prep (DetCN (DetQuant DefArt NumPl) (UseN house_N))
nelle case   -- not "in le case"

> cc -one PrepNP with_Prep (DetCN (DetQuant DefArt NumPl) (UseN cat_N))
coi gatti    -- not "con i gatti"

这就是为什么我们需要在屈折表中区分大小写。如果我用你写的内容替换 somePl_Det,我会得到这个:

> cc -one PrepNP with_Prep (DetCN somePl_Det (UseN cat_N))
alcuni gatti   -- "with" is missing!

> cc -one PrepNP in_Prep (DetCN somePl_Det (UseN house_N))
alcuni case    -- "in" is missing,and no gender agreement!

如何实际修复 somePl_Det

这似乎需要在上游修复,而不是针对每个人的本地语法单独进行黑客攻击。

line 86 in StructuralIta 替换为:

  somePl_Det = {s,sp = \\g,c => prepCase c ++ genForms "alcuni" "alcune" ! g ; n = Pl ; s2 = [] ; isNeg = False} ;

重新编译你的 RGL,从现在开始,你应该得到这个输出:

> cc -one PrepNP in_Prep (DetCN somePl_Det (UseN house_N))
in alcune case

> cc -one PrepNP with_Prep (DetCN somePl_Det (UseN cat_N))
con alcuni gatti

如果您对 gf-rgl 存储库进行了分叉,并在您自己的分支中修复此问题,那么您可以从您的分支发出拉取请求并将其合并到上游。