I'm playing with Haskell return-type polymorphism using the following function:
f :: [a] -> [a]
f [] = mempty
f (x:xs) = [x] <> f xs
Obviously it does nothing. What I'd like to do is to modify the type so that it takes a list and returns a Monoid container, one of which could be a list. I'm stuck here because Monoid
takes one type argument. I have no idea what the type could be: f :: Monoid m => [a] -> ?
Is this possible?
As you note, you can't turn an arbitrary a
into a member of any specific Monoid m
without a function of type a -> m
available. But there is no such function that works for all Monoid instances - if there were, it'd have to be in the typeclass definition, and you can see it doesn't exist.
Therefore, you have to either specialize f
to a particular Monoid, as you did here for the [a]
Monoid; or else accept a transforming function a -> m
in addition to the [a]
. That is, your type could become:
combine :: Monoid m => (a -> m) -> [a] -> m
And if we ask Hoogle about this type , we see that your function is already defined (generalizing list to Foldable):
foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m
You may find it a useful exercise to implement foldMap
, either for Foldables in general or specialized to lists.
As @amalloy said, you need a way to put your list's contents into your "monoid container" - the Monoid class does not define such a thing, so either your list's contents need to already constitute a monoid (in which case, your function is just mconcat
):
f :: Monoid m => [m] -> m
f = mconcat
or you provide a converter function (in which case you transform the list's contents into your monoid, then do mconcat:
f :: Monoid m => (a -> m) -> [a] -> m
f converter = mconcat . fmap converter
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.