Ben Weaver
Ben Weaver

Reputation: 970

Haskell troubles with very simple record syntax

Although a Haskell newbie, I have used records before. They are easy to use. But now, when I wish to pull some data from a record, I am getting a 'found hole' error. The offending code is:

let theSchemaId =  _schemaId schema

where the record is defined thus:

data Schema = Schema
  { _schemaId         :: !SchemaId

   , [   other fields ... ]
  }

This seems perfectly straight forward to me, similar to records I have used before. However, when running the line of code above, I get the following error below. All imports are in place. Any ideas as to its cause?

the error:

 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

Upvotes: 2

Views: 229

Answers (1)

K. A. Buhr
K. A. Buhr

Reputation: 50864

As you are undoubtedly aware, unrecognized identifiers in Haskell code generate error messages. For example, the program:

foo = noSuchIdentifier 10

generates the error message:

HolyFields.hs:5:7-22: error:
    Variable not in scope: noSuchIdentifier :: Integer -> t

Unrecognized identifiers that start with an underscore also generate error messages, but the messages are different because the identifiers are treated as typed holes. For example, the program:

bar = _underscoredIdentifier 10

generates the error message:

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

BUT, if an identifier is known, there is no error whether or not it starts with an underscore. The following program compiles fine:

_noProblem = (*2)
quux = _noProblem 10

The situation is no different for identifiers that happen to name fields.

Therefore, the problem you're seeing is that, even though you think the field _schemaId is in scope at the point of use, it is not. You have perhaps forgotten to load the module that contains its definition, or the module has an export list that excludes it.

In particular, note that if you export only Schema, like so:

module MyModule (Schema) where
data Schema = ...

this will not export Schema's constructors or field functions. You need to instead write:

module MyModule (Schema(..)) where
data Schema = ...

in order for _schemaId to be in scope in the importing module.

Upvotes: 10

Related Questions