Hide constructor, but not import type.

I have an internal module that I would like to provide an external API for

module Positive.Internal where newtype Positive a = Positive { getPositive :: a } deriving (Eq, Ord) -- smart constructor toPositive :: (Num a, Ord a) => a -> Maybe (Positive a) toPositive a | a <= 0 = Nothing | otherwise = Just $ Positive a -- ... 

I want to hide the mute constructor and replace it with a unidirectional template so that users can still match match values, they just need to use the smart designer to use the new values.

Since I want the template and the mute constructor to use the same name, I need to hide the mute constructor to prevent namespace conflicts.

However, since the mute constructor and type section names are, it is a little more difficult to import everything except the mute constructor.

I am currently doing this, which works fine:

 {-# LANGUAGE PatternSynonyms #-} module Positive ( module Positive.Internal, pattern Positive ) where import Positive.Internal (Positive()) import Positive.Internal hiding (Positive) import qualified Positive.Internal as Internal pattern Positive :: a -> Positive a pattern Positive a <- Internal.Positive a 

I could simplify imports simply by using qualified imports, but I'm curious.

Is there a way to import all Positive.Internal in one import statement, except for the silent constructor?

I tried hiding (Positive(Positive)) , but this hid both the type and the dumb constructor. I quoted a wiki , but I did not notice any way to distinguish between constructors and types in hiding lists.

+7
module haskell
source share
1 answer

Correct me if I'm wrong, but I'm pretty sure this is what you are looking for:

 {-# LANGUAGE PatternSynonyms #-} module Positive ( module Positive.Internal, pattern Positive, foo ) where import Positive.Internal hiding (pattern Positive) import qualified Positive.Internal as Internal (pattern Positive) pattern Positive :: a -> Positive a pattern Positive a <- Internal.Positive a foo :: Positive Int foo = Internal.Positive 5 

Internal module remains the same as defined so far. And for an example:

 module Negative where import Positive bar :: Maybe Int bar = getPositive <$> toPositive 6 

Let double check in GHCi:

 Prelude> :load Negative [1 of 3] Compiling Positive.Internal ( Positive/Internal.hs, interpreted ) [2 of 3] Compiling Positive ( Positive.hs, interpreted ) [3 of 3] Compiling Negative ( Negative.hs, interpreted ) Ok, modules loaded: Negative, Positive, Positive.Internal. *Negative> bar Just 6 *Negative> getPositive foo 5 *Negative> :i Positive newtype Positive a = Positive.Internal.Positive {getPositive :: a} -- Defined at Positive/Internal.hs:3:1 instance [safe] Ord a => Ord (Positive a) -- Defined at Positive/Internal.hs:4:17 instance [safe] Eq a => Eq (Positive a) -- Defined at Positive/Internal.hs:4:13 *Negative> :t Positive <interactive>:1:1: error: • non-bidirectional pattern synonym 'Positive' used in an expression • In the expression: Positive 
+3
source share

All Articles