问题描述
我之前问过一个关于扩展 which_RP 记录的问题,并将此问题 here 下的关系从句 "that" 更改为 "which"。
最近我开始研究意大利语,每当我使用 someSg_Det 或 somePl_Det 函数时,我都会分别得到以下结果。
qualche albero
qualche alberi
根据我对意大利语的了解,我知道对于单名词 qualche albero
是正确的,但是对于复数名词,我们必须根据名词的性别使用 alcune
或 alcuni
.因此,我尝试将函数 somePl_Det 扩展到 somePlM_Det 和 somePlF_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
} ;
注意类型为 s
的 Gender => Case => Str
字段。这是两个嵌套列表,而您试图只给它一个列表。
这行得通,但没有意义:
somePlF_Det : Str -> Det =
\str ->
somePl_Det ** {s = table {_ => table {_ => "alcune"}}};
这有什么问题?两件事,解释如下。
Det
有变量 Gender
– 不是固有的
在 RGL 中,那些有性别或其他名词类的语言,通常设计如下。
名词(以及通过继承 CN
和 NP
)具有固有的性别。这意味着他们的 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.g
从 mod.s
中选择字符串。变量 x
可以表示任何其他屈折特征,例如大小写或数字---对于本示例无关紧要。
因此定义 somePlM_Det
和 somePlF_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 存储库进行了分叉,并在您自己的分支中修复此问题,那么您可以从您的分支发出拉取请求并将其合并到上游。