问题
This question shows an instance definition for (,) a b
, where a
is an instance of Monoid
.
However, I don't know how to write similar thing for (,) a b
, and b
is an instance of Monoid
? I can basically do this as long as I can write the definition:
instance Monoid b => Monad ((,) ???) where
return a = (a,mempty)
~(a,b) >>= f = let (c,b1) in f a in (c,b `mappend` b1)
So the question is how to write the ???
part?
UPDATE
Actually this question is special case of a more generic problem: is it possible to write instance of type classes that act on some types that is not appear at the end? In my case, the type constructor is (,) a b
, and I want to make it an instance of Monad a
where a
is not the last type parameter.
回答1:
We could write, for now synonyms works inappropriate for this case, so we use newtype:
newtype RevTuple b a = RevTuple { totuple :: (a , b) }
instance Monoid b => Monad (RevTuple b) where
return a = RevTuple (a,mempty)
(RevTuple (a,b)) >>= f =
let RevTuple (c,b1) = f a in RevTuple (c,b `mappend` b1)
回答2:
You cannot. It's crucial for Monad
to be polymorphic in its parameter, so if a particular monadish thing only makes sense for monoids, it's not a monad.
For example, return :: Monad m => a -> m a
. There's no way you can add an extra constraint to the signature of return
.
来源:https://stackoverflow.com/questions/19196333/monad-instance-for-pairs