Well, you can't.
Set
is an abstract data type[0] that deliberately hides its internal representation, primarily to maintain invariants of the data structure that can't be statically-enforced by the type system (specifically, the standard library Data.Set.Set
is a binary search tree).
Losing the ability to pattern match on an abstract data type is an unpleasant bit of collateral damage, but oh well. Your options are roughly:
- Use boolean predicates and guards, e.g.
null
, as in trinithis's answer.
- Convert the
Set
to a list. Most of the time this is silly but if you want to iterate through the set anyway, it works well enough.
- Enable GHC's
ViewPatterns
extension, which provides syntactic sugar for using accessor functions where a pattern match would normally go.
- Avoid making these sort of checks in the first place--if you have a
Set
, treat it like a set, and work with it as a whole for mapping, filtering, etc. Not always possible, but can lead to cleaner code with fewer explicit conditionals/iterations.
View patterns would let you write something that looks like this:
foo (setView -> EmptySet) = []
foo (setView -> NonEmpty set) = other_thing
...where setView
is a function you write. Not really much of a gain here, but can be nice for more complex pseudo-patterns
For avoiding explicit checks, besides well-known set operations such as union
and intersection
, consider making use of the filter
, partition
, map
, and fold
functions in Data.Set
.
[0]: See this paper (warning: PDF) for the definition of the term as I'm using it.