This makes T fully abstract, which is what I'm trying to avoid. Private types provide an intermediate level of abstraction. The real example I have involves defining a type with numerous constructors (or a record with numerous fields), and I'd like to avoid writing all the corresponding destructors. Even if I did do this, it burdens clients of the module by requiring them to use the alternative destructors.
Hi
I don't think there is a direct equivalence. You can make T an opaque
type using a module where you do not export the constructor. However,
you can't then pattern match on the type so you have to supply a
destructor - here called unT. Any module that imports XYZ only sees
the type T, the 'handmade' constructor makeT and the destructor unT:
module XYZ
(
T, -- this does not export the constructor
unT
makeT
) where
data T = PrivateT Int deriving (Eq,Show)
unT :: T -> Int
unT (PrivateT i) = i
-- Add any checking you want here...
makeT :: Int -> T
makeT i = PrivateT i