11

I am ploughing through Learn You a Haskell for Great Good, and I have reached up to section 8.4, "Derived Instances". In this section, there's the following data type declaration:

data Person = Person { firstName :: String  
                     , lastName :: String  
                     , age :: Int  
                     } deriving (Eq)

While trying

*Main> mikeD == Person {firstName = "Michael", lastname = "Diamond", age = 43}

I got the following error:

<interactive>:55:41:
`lastname' is not a (visible) field of constructor `Person'

By correcting lastname to lastName I removed the error.

Question:

In the error message the word (visible) hints to me that there must be the possibility of declaring a field as hidden / invisible. Is this correct or not? If it is, how can I declare a field in the constructor as hidden, and what are the general scenarios where one would need to declare hidden fields? If you could explain this by giving a simple example of their use, that would be appreciated.

Note: I could not find any reference to/details about hidden or invisible field in LYAH.

Antal Spector-Zabusky
  • 36,191
  • 7
  • 77
  • 140
Optimight
  • 2,989
  • 6
  • 30
  • 48

1 Answers1

11

It is possible to hide a field of a record, or a constructor of any data type, although not at the declaration site. The idea is to simply choose not to export that constructor and/or field from the module, like so:

module MyModule (DT(C1, int, mStr)) where

data DT = C1 -- visible
             { 
               int :: Int, -- visible
               str :: String -- hidden
             }
        | C2 -- hidden
             {
               dbl :: Double, -- hidden
               mStr :: Maybe String -- visible
             }

Note that everything inside MyModule still has access to both constructors and all four fields, but in some other module that imports MyModule only the exported ones are visible.

Ptharien's Flame
  • 3,246
  • 20
  • 24
  • 3
    "It is not possible to export some fields of a given constructor and not other fields of the same constructor, however." Yes, it is. `module MyModule (DT(C1, int))` only exports `int`, but not `str`. Also note that your `DT(C1)` does not export any of the fields, so `int` and `str` are invisible in your code sample. – sepp2k Jul 23 '12 at 07:07
  • @sepp2k I did not know that! I will correct my answer, thank you. – Ptharien's Flame Jul 23 '12 at 07:09
  • 1
    "only visible as a function, not as a field" — not true either. You can use it to update the record. – Roman Cheplyaka Jul 23 '12 at 08:29
  • 1
    No, it's not corrected. The way you export it doesn't matter. What you're trying to achieve ("only visible as a function, not as a field") is simply not possible. For that, you have to define it as a function, not as a field. – Roman Cheplyaka Jul 23 '12 at 20:37