Haskell 使用非常简单的记录语法遇到麻烦

Ben*_*ver 3 haskell record

虽然是 Haskell 新手,但我之前使用过记录。它们易于使用。但是现在,当我希望从记录中提取一些数据时,出现“发现漏洞”错误。违规代码是:

let theSchemaId =  _schemaId schema
Run Code Online (Sandbox Code Playgroud)

其中记录是这样定义的:

data Schema = Schema
  { _schemaId         :: !SchemaId

   , [   other fields ... ]
  }
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎非常直接,类似于我以前使用过的记录。但是,在运行上面的代码行时,出现以下错误。所有进口都到位。关于其原因的任何想法?

错误:

 src/master/haskell-service/src/Handler/Strategy/Components/View.hs:695:34: error:
    src/master/haskell-service/src/Handler/Strategy/Components/View.hs:695:34: error:
    • Found hole: _schemaId :: Schema -> SchemaId
      Or perhaps ‘_schemaId’ is mis-spelled, or not in scope
    • In the expression: _schemaId
      In the expression: _schemaId schema
      In a pattern binding: theSchemaId :: SchemaId = _schemaId schema
    • Relevant bindings include
        theSchemaId :: SchemaId
Run Code Online (Sandbox Code Playgroud)

K. *_*uhr 11

您无疑知道,Haskell 代码中无法识别的标识符会生成错误消息。例如,程序:

foo = noSuchIdentifier 10
Run Code Online (Sandbox Code Playgroud)

生成错误消息:

HolyFields.hs:5:7-22: error:
    Variable not in scope: noSuchIdentifier :: Integer -> t
Run Code Online (Sandbox Code Playgroud)

以下划线开头的无法识别的标识符也会生成错误消息,但消息是不同的,因为标识符被视为类型化的holes。例如,程序:

bar = _underscoredIdentifier 10
Run Code Online (Sandbox Code Playgroud)

生成错误消息:

HolyFields.hs:1:7-28: error:
    • Found hole: _underscoredIdentifier :: Integer -> t
      Where: ‘t’ is a rigid type variable bound by
               the inferred type of bar :: t
               at HolyFields.hs:1:1-31
      Or perhaps ‘_underscoredIdentifier’ is mis-spelled, or not in scope
Run Code Online (Sandbox Code Playgroud)

但是,如果标识符是已知的,则无论它是否以下划线开头都没有错误。以下程序编译良好:

_noProblem = (*2)
quux = _noProblem 10
Run Code Online (Sandbox Code Playgroud)

对于名称字段中出现的标识符,情况也没有什么不同。

因此,您所看到的问题是,即使您认为该领域_schemaId在使用时处于范围内,但事实并非如此。您可能忘记加载包含其定义的模块,或者模块具有排除它的导出列表。

特别要注意的是,如果您只导出Schema,像这样:

module MyModule (Schema) where
data Schema = ...
Run Code Online (Sandbox Code Playgroud)

这不会导出Schema的构造函数或字段函数。你需要写:

module MyModule (Schema(..)) where
data Schema = ...
Run Code Online (Sandbox Code Playgroud)

以便_schemaId在导入模块的范围内。