Reputation: 18069
So I've got a structure like this:
data Maybe a = Nothing | Just a
but I want a structure that is defined as
data MaybeInt = Nothing | Just Int
is there a way to define MaybeInt
using Maybe a
, and if so how?
Upvotes: 1
Views: 958
Reputation: 74344
There are a few ways to define MaybeInt
. I'll state them then have some commentary.
Direct
data MaybeInt = NothingInt | JustInt Int
Newtype
newtype MaybeInt = MI (Maybe Int)
Type synonym
type MaybeInt = Maybe Int
Plain
-- just use `(Maybe Int)` wherever you would write `MaybeInt`
Commentary
Most commonly, one would use the plain method since most people are familiar with Maybe
and thus know to use Just
and Nothing
to match it. This makes it good for libraries—very transparent. The type synonym method is a common documentation method, but is basically useless for your synonym. It makes it so that foo :: Int -> Maybe Int
and bar :: Int -> MaybeInt
have identical type signatures. It also means that as soon as someone knows that MaybeInt === Maybe Int
they can use the Just
/Nothing
constructors for matching.
The newtype method gets fairly interesting. Here you have to begin "wrapping" and "unwrapping" the MI
constructor every time you want to use the MaybeInt
type. Compare:
baz :: MaybeInt -> Bool
baz (MI Nothing) = False
baz (MI (Just int)) = True
this is nice because if you don't export MI
then nobody will be able to match on MaybeInt
(despite having a pretty good guess at what's going on inside of it). This is really useful for making stable APIs. Another interesting property of newtype
is that you can write new instance
s for MaybeInt
which are different from Maybe
's built-in ones. For instance, you could override the Monoid
instance
instance Monoid MaybeInt where
mempty = MI Nothing
mi `mappend` (MI Nothing) = mi
_ `mappend` mi = mi
which is just the same as the Last a
newtype built-in to Data.Monoid
which wraps Maybe a
s.
Finally, we get the full-blown data
instance. It's more verbose, more likely to error, marginally slower (since the compiler has to track a new, unique data type), and requires that people learn new constructors. For functionality so obviously identical to Maybe Int
there's really no reason to use it at all.
Upvotes: 10