[Haskell-beginners] question, chapter 10 Real World Haskell

Michael Mossey mpm at alumni.caltech.edu
Sat Apr 11 12:37:53 EDT 2009

Daniel Fischer wrote:
> In a real library, the constructor Parse would not be exported, to allow later changing 
> the implementation of the Parse type without breaking user code.
> So user code like parseByte cannot access the constructor and must use the exported API 
> (getState, putState, identity, bail, ...).

thanks for the point, I get it. One other question. Later in the chapter they define
peekByte as follows:

-- file: ch10/Parse.hs
peekByte :: Parse (Maybe Word8)
peekByte = (fmap fst . L.uncons . string) <$> getState

Here they are accessing the 'string' field of the state. So whomever writes this 
function needs to have the accessor functions. At this point I'm wondering how much 
state is really getting hidden. Or maybe peekByte would only be written inside the 
original library.

I was just playing around and discovered you can choose to export the accessor 
functions or not. Let's say we have

module Mod where

data What = What { acc :: Int64 }

now in a separate module we write:

-- All fine:
import Mod
x1 = What 3
x2 = What { acc = 3 }
x3 = acc x1


Now we revisit the first module and write
module Mod ( What(What) ) where

import Mod
x1 = What 3             -- Fine
x2 = What { acc = 3 }   -- Error
x3 = acc x1             -- Error

So apparently this exports the constructor but not the accessor fields. The item can 
be constructed in the normal way, but not in record syntax way.

module Mod ( What(acc) ) where
   --> This exports the accessors which can be used to access, but not to construct

module Mod (What(..)) where
    --> export everything

So the lesson is, if we are going to allow users to write functions like peekByte, we 
have to export the accessor functions, but not necessarily any constructors.

More information about the Beginners mailing list