为了练习,我在名为“队列”的模块中实现队列数据类型。我的数据类型也称为“队列”,它也是唯一的值构造函数:

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)...

据我了解,因为我在export语句中写了Queue,而不是Queue(..)Queue(Queue),所以我不希望模块会导出我的数据类型的值构造函数。这正是我想要的,出于封装的目的:用户不应直接使用值构造函数;我的界面中只有emptyQueueenq和其他功能。

但是(对于经验丰富的Haskellers,解决问题的方法可能很明显),如果我将模块加载到GHCi中,则可以直接使用值构造函数。
$ 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]}

如上所述,这是不希望的。我究竟做错了什么?

最佳答案

你什么都没做错。只是为了方便起见,ghci忽略了对其加载的模块的作用域规则。

如果您想查看正常情况下可以使用的功能,则可以

:m -Queue
:m +Queue

您可以稍后使用以下命令返回“一切可用”模式
:m *Queue

另请参见官方文档中的What's really in scope at the prompt?

关于haskell - 为什么即使不导出也可以使用我的值构造函数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28116009/

10-10 05:43