简体   繁体   中英

How to turn a function returning [a] into a function returning a Monoid?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM