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.

I think the feature I'm looking for is "guarded constructors", but to my knowledge there is no such thing.


On Thu, Apr 8, 2010 at 3:42 PM, Stephen Tetley <stephen.tetley@gmail.com> wrote:
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