I have three functions (getRow,getColumn,getBlock) with two arguments (x and y) that each produce a list of the same type. I want to write a fourth function that concatenates their outputs:
outputList :: Int -> Int -> [Maybe Int]
outputList x y = concat . map ($ y) $ map ($ x) [getRow,getColumn,getBlock]
The function works, but is there a way to rewrite the double map (with three ‘$’s) to a single map?
You deserve an explanation.
First, I’ll explicitly note that all these functions have the same type.
Now let’s start with your original definition.
These functions result in a
[Maybe Int], and a list of anything is a monoid. Monoidally combining lists is the same as concatenating the lists, so we can replaceconcatwithmconcat.Another thing that’s a monoid is a function, if its result is a monoid. That is, if
bis a monoid, thena -> bis a monoid as well. Monoidally combining functions is the same as calling the functions with the same parameter, then monoidally combining the results.So we can simplify to
And then again to
We’re done!
The Typeclassopedia has a section about monoids, although in this case I’m not sure it adds that much beyond the documentation for Data.Monoid.