Search code examples
haskelloption-typemonoids

Haskell: Better way of writing Maybe Endo?


I have just discovered the Endo type thanks to the network-api-support package and I have found the need to be able to throw Maybe values into Endo's. As a result I have written a function called maybeEndo. Here is an example of it being used:

setProxy :: Proxy -> RequestTransformer
setProxy (Proxy pHost pPort) = Endo $ addProxy pHost pPort

maybeEndo :: (a -> Endo b) -> Maybe a -> Endo b
maybeEndo _ Nothing = Endo id
maybeEndo f (Just v) = f v

setPotentialProxy :: Maybe Proxy -> RequestTransformer
setPotentialProxy = maybeEndo setProxy

What strikes me is that this seems like something that should be encapsulated into some type of pattern already.


Solution

  • You already found maybe (Endo id). But Endo is an instance of Monoid, and Endo id is its neutral element mempty. So you could also write more generally

    maybeMonoid :: Monoid b => (a -> b) -> Maybe a -> b
    maybeMonoid = maybe mempty
    

    This is already quite idiomatic (plenty of hits when you google for "maybe mempty"). You can be even more general by using a function from Data.Foldable:

    foldMap :: (Foldable t, Monoid b) => (a -> b) -> t a -> b
    

    so with this, you can write

    setPotentialProxy :: Maybe Proxy -> RequestTransformer
    setPotentialProxy = foldMap setProxy
    

    (but make sure you leave in the type signature, otherwise you’ll spend too much time figuring it out later when you read the code :-)).