Reputation: 2985
Suppose I want to make all numbers an instance of Monoid
. Instead of having to create an instance for each Num
like this:
instance Monoid Int where
mappend = (+)
mempty = 0
instance Monoid Float where
mappend = (+)
mempty = 0.0
-- etc
Is there something like this?
instance Num t => Monoid t where
mappend = (+)
mempty = 0
Some are answering with GHC extensions and warning about the potential issues; I found that informative, but I think I will stick with Sum
, Product
and whatever coerce
does.
Upvotes: 8
Views: 191
Reputation: 1374
I'm interpreting this as asking about a general premise, rather than specifically about Monoid
and Num
.
Maybe you could get what you wrote to work, by enabling language extensions FlexibleInstances, UndecidableInstances, and using overlapping instances.
But you probably wouldn't want to: it seems like instance Num t => Monoid t where ...
is saying
"If t
is an instance of Num
, here's how to make t
an instance of Monoid
..."
Unfortunately, that's not right. What it's actually saying is more like
"Here's how to make t
an instance of Monoid.
First, it's necessary that t
be an instance of Num
. Next..."
Thus, if you write an instance declaration like this, you can't write any other instance declarations. (At least not without OverlappingInstances
, which would bring its own issues.)
Upvotes: 21
Reputation: 24814
GHC allows your definition with some language extensions enabled
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
instance Num t => Monoid t where
mappend = (+)
mempty = 0
This makes 2 <> 3
result in 5
.
But this overlaps with other Monoid
instances, so trying to evaluate "Hello" <> "World"
results with an error: Overlapping instances for Monoid [Char]
So, I think that the short answer is: no.
Upvotes: 6