Search code examples
haskellfactory-pattern

Guards in a Haskell constructor or factory methods with visibility constraints


Rather new to Haskell and experimenting I came across a problem which looks like I would want to use guards in a constructor. My real experiment is a bit more involved, but it comes down to something like

data X a = Zero
   | a==0 = Zero
   | otherwise = Some a

I know this is wrong syntax, in particular because a is a type variable, not a value variable, so a==0 is nonsensical anyway.

The background is that the values Zero and Some 0 shall be equal in all regards, I would even say identical. In fact I never want to construct a Some 0, this should be forbidden or, as drafted above, silently converted to Zero already in the constructor.

I would think there is a common idiom in Haskell for this. In Java I would just make the two constructors private and provide factory methods to create either one or the other with some(0) returning Zero instead of Some(0). Is this how you would to this in Haskell too?

EDIT: Ok, googling some more I finally found the Haskell Factory Function entry, which seems to be part of the answer.


Solution

  • To make a constructor private, just don't export it, e.g.:

    module Foo (Bar, mkBar) where
    
    data Bar = Zero | Some a | ...
    
    mkBar :: Int -> Bar  -- exported smart constructor
    mkBar a = ...
    

    Users of the library can use the mkBar function to create a Bar, but not Zero or Some ....

    The key is the Bar in the export list. If you had specified:

    module Foo (Bar(..), ...) where
    

    then the constructors for Bar would also be exported.