Suppose I have a module that contains a type:
module My where
data L a = Nil | Cons a (L a)
The module exports the concrete definition of My
to allow for pattern matchi开发者_C百科ng etc.
Is it possible for another module, say Client
to import My
in a manner where L a
is abstract i.e. such that pattern matching on L a
values is prohibited by the type-checker?
Yes; you just have to use the import list:
module Client where
import My (L)
ok :: L Int
ok = undefined
bad :: L Int
bad = Cons 3 Nil
bad2 :: L Int -> Int
bad2 (Cons i _) = i
bad2 Nil = 0
If you try to compile this, you'll get the following four errors:
Client.hs:8:10: Not in scope: data constructor `Cons'
Client.hs:8:17: Not in scope: data constructor `Nil'
Client.hs:11:10: Not in scope: data constructor `Cons'
Client.hs:12:9: Not in scope: data constructor `Nil'
If you did want to import the constructors, you would instead specify L(..)
, or L(Cons)
to import Cons
but not Nil
.
For some other ways you can use the import
statement, check out the HaskellWiki article on import
(although the article doesn't mention importing data types and their constructors).
Yes, you may do
import My(L())
to import a type without importing any of its constructors. If you still wish to construct values of this type (but not pattern match), you must import functions for doing that construction (for example, by exporting such functions from My
or by creating a utility module with such functions).
edit: Since you explicitly mentioned that you wanted a type-checking error, I should point out for completeness that this won't cause pattern-matching on Nil
and Cons
to be a type-checking error, but merely a scoping error.
精彩评论