8

For practice, I'm implementing a queue data type in a module called "Queue". My data type is also called "Queue", as is its only value constructor:

module Queue (Queue, enq, emptyQueue) where

data Queue a = Queue {
  inbox  :: [a],
  outbox :: [a]
} deriving (Eq, Show)

emptyQueue :: Queue a
emptyQueue = Queue [] []

enq :: a -> Queue a -> Queue a
enq x (Queue inb out) = Queue (x:inb) out

-- other function definitions (irrelevant here)...

As far as I understand, because I wrote Queue, not Queue(..) or Queue(Queue) in the export statement, I don't expect the value constructor of my data type to be exported by the module. This is exactly what I want, for encapsulation purposes: users should not be able to use the value constructor directly; only emptyQueue, enq, and the other functions in my interface.

However (and the solution to my problem may be obvious to seasoned Haskellers), if I load my module in GHCi, I'm able to use the value constructor directly.

$ ghci Queue.hs
GHCi, version 7.8.4: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Queue            ( Queue.hs, interpreted )
Ok, modules loaded: Queue.

λ> Queue [1] [2] 
Queue {inbox = [1], outbox = [2]}

As stated above, this is undesirable. What am I doing wrong?

jub0bs
  • 60,866
  • 25
  • 183
  • 186
  • 2
    possible duplicate of [Why can ghci see non-exported types and constructors? How can I fix it?](http://stackoverflow.com/questions/27548049/why-can-ghci-see-non-exported-types-and-constructors-how-can-i-fix-it) – dfeuer Jan 23 '15 at 18:39
  • @dfeuer Sorry, I wasn't aware of the question you link to. – jub0bs Jan 23 '15 at 18:46

1 Answers1

14

You are doing nothing wrong. It's just that, for convenience, ghci ignores scoping rules on modules it loads.

If you want to see what would normally be available, you can

:m -Queue
:m +Queue

You can later return to the "everything is available" mode with

:m *Queue

See also What's really in scope at the prompt? in the official documentation.

Daniel Wagner
  • 145,880
  • 9
  • 220
  • 380
  • 1
    Ah yes! Thanks; I wasn't aware of that. It's not the first time GHCi plays tricks on me. Please add a reference to the documentation about GHCi ignoring scoping rules by default, and I'll accept your answer. – jub0bs Jan 23 '15 at 18:10
  • We really should try to pick one canonical question for this issue. It comes up a *lot*. – dfeuer Jan 23 '15 at 18:39