Dla celów praktycznych implementuję typ danych kolejki w module o nazwie "Kolejka". Mój typ danych jest również nazywana „Kolejka”, jak to jest tylko jego konstruktor wartość:Dlaczego mogę używać mojego konstruktora wartości, mimo że go nie eksportuję?
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)...
O ile mi zrozumieć, bo pisałem Queue
, nie Queue(..)
lub Queue(Queue)
w rachunku eksportu, nie oczekuj konstruktor wartości mojego typu danych do wyeksportowania przez moduł. Dokładnie tego chcę, do celów enkapsulacji: użytkownicy nie powinni mieć możliwości bezpośredniego użycia konstruktora wartości; tylko emptyQueue
, enq
i inne funkcje w moim interfejsie.
Jednak (i rozwiązanie mojego problemu może być oczywiste dla wytrawnych Haskellerów), jeśli załaduję mój moduł w GHCi, jestem w stanie bezpośrednio użyć konstruktora wartości.
$ 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]}
Jak wspomniano powyżej, jest to niepożądane. Co ja robię źle?
możliwy duplikat [Dlaczego ghci może zobaczyć nieeksportowane typy i konstruktory? Jak mogę to naprawić?] (Http://stackoverflow.com/questions/27548049/why-can-ghci-see-non-exported-types-and-constructors-how-can-i-fix-it) – dfeuer
@ dfeuer Przepraszamy, nie wiedziałem o pytaniu, które łączysz. – Jubobs