将字段声明为 `f: elems[g] -> one h` 会产生名称未找到错误。我错过了什么?

Declaring a field as `f: elems[g] -> one h` is producing a name-not-found error. What am I missing?

在我正在编写的模型中,我想说的是阅读手稿会识别手稿中的一系列标记并将它们映射到类型;应该为手稿中的所有标记定义映射,并且应该为每个标记准确地标识一种类型。 (此处的类型和标记如 Peirce 的 type/token distinction 所述。)

当我写作时

sig Document, Type, Token {}
sig Reading {
  doc: Document,
  tokens: seq Token,
  mapping:  elems[tokens] -> one Type
}
run {} for 3

尝试执行 run 命令会产生错误消息

The name "elems" cannot be found.

如果我将 elems[tokens] 替换为 seq/Int.tokens(借用 util/sequiv 中 elems 的定义)或(简化)Int.tokensuniv.tokens, 我得到了我期望的结果。

如果我将 elems[tokens] 替换为 ran[tokens](并包括 open util/relation),我会收到关于名称 ran.

的类似投诉

在模型的其他地方使用这些名称(未显示)不会引发此错误,因此我推断问题不在于所讨论的函数未知,而是函数调用在 a 的右侧不受欢迎字段声明。

语法只说字段声明的右侧是一个表达式,函数调用可以作为表达式。所以我想在其他地方表达了一个约束,解释了为什么我的初始公式不起作用。谁能告诉我这是什么?

我现在可以使用 univ.tokens,但我更喜欢原始的表述,因为我的预期读者更容易理解——他们可以眯着眼睛将其视为函数调用,而使用点join 我需要停下来向他们解释,这会分散模型的核心任务。感谢您的帮助。

我试了一下这个例子,看来你的推论是正确的。不能在字段声明中引用函数(即使语法另有说明)

你提出的(univ.tokensInt.tokens)对我来说是最干净的解决方法。

Peter 在他的评论中提出的建议确实有效,但重新定义 elems 看起来太可疑了,特别是因为 elems 函数已经为您的读者明确定义。这可能会造成混淆。

如果你真的坚持使用 elems[token] 的另一个想法是将映射定义为从 TokenType 的关系,然后限制关系的左侧仅包含序列中存在的那些 Token。这就是您的模型:

sig Document, Type, Token {}
sig Reading {
  doc: Document,
  tokens: seq Token,
  mapping: Token -> one Type
}{
    mapping.Type =elems[tokens]
}

run {} for 3