1

If I have a module containing

data Foo = Bar Int | Baz Bool

can I export Bar and Baz in their role as "pattern matchers" or "destructors" only and not allow the module user to construct values of type Foo using them?

That is, I want to permit the usage

f (Bar i) = ... i ...

but prevent the usage

x = Bar i
Tom Ellis
  • 9,224
  • 1
  • 29
  • 54

1 Answers1

5

No. Pattern matches are defined in terms of constructors. You either export them and therefore enable users to pattern match and create new Foos, or you don't.

If you just want to prevent a user to create some internal type, you could use an intermediate one:

module Foo (Foo, FooRep(..), toRep) where

data Foo    = Bar Int  | Baz Bool
data FooRep = BarR Int | BazR Bool

toRep (Bar i) = BarR i
toRep (Baz b) = BazR b
import Foo

f foo = case (toRep foo) of
           BarR i -> ... 
           BazR b -> ...
Zeta
  • 103,620
  • 13
  • 194
  • 236
  • 1
    Actually, this is possible now in GHC 7.8 with unidirectional pattern synonyms: `data Foo = Bar' Int | Baz' Bool; pattern Bar n <- Bar' n; pattern Baz n <- Baz' n`. Then, you can just export those pattern synonyms. They will allow `example (Baz n) = ...` but not `example' = Baz ...`. – David Young Aug 06 '14 at 19:13
  • @DavidYoung: [Joachim already mentions this in the older question](http://stackoverflow.com/questions/8172548/is-it-possible-to-export-constructors-for-pattern-matching-but-not-for-construc). Still this question is about whether it's possible to export constructors as pattern-matchers only, so "No" as an answer holds, since you have something different than `Foo` or `Bar` at the end :). – Zeta Aug 06 '14 at 19:21