In a 1988 paper called *Algebraic Identities for Program Calculation*, Richard Bird wrote:

Probably the most useful law about map is the fact that it distributes over functional composition: (map f) . (map g) = map (f . g)

Bird’s paper predates Haskell, and instead uses a language called Miranda, but Haskell later adopted very similar notation:

```
GHCi, version 6.12.1: http://www.haskell.org/ghc/ :? for help
Prelude> let f x = x * x
Prelude> let g x = x + 1
Prelude> ((map f) . (map g)) [1 .. 5]
[4,9,16,25,36]
Prelude> map (f.g) [1 .. 5]
[4,9,16,25,36]
```

I am a sucker for nice notation, and that is some very nice notation. It got me thinking about how I might write the same thing in Clojure. Here is my first cut at a literal translation:

```
user> ((comp (partial map sq) (partial map inc)) (range 1 6))
(4 9 16 25 36)
user> (map (comp sq inc) (range 1 6))
(4 9 16 25 36)
```

The Clojure code looks a little noisy by comparison, mostly due to the explicit use of **partial**. I came up with a couple of variations on map that clean up the presentation. The first I call **mapp**:

```
(defn mapp
([f] (partial map f))
([f x & args]
(apply map (partial f x)
args )))
```

Here are some examples of mapp in action:

```
;; Using regular old map
user> ((comp (partial map sq) (partial map inc)) (range 1 6))
(4 9 16 25 36)
;; We can clean that up a bit with mapp
user> ((comp (mapp sq) (mapp inc)) (range 1 6))
(4 9 16 25 36)
;; Or you can do stuff like this
user> (mapp * 100 (range 6))
(0 100 200 300 400 500)
user> (mapp + 1/2 (range 6))
(1/2 3/2 5/2 7/2 9/2 11/2)
```

My other variation on map is called **mapc**.

```
(defn mapc [& args]
(let [[fns xs] (partition-by fn? args)
g (apply comp fns)]
(if (empty? xs)
(partial map g)
(apply map g xs ))))
```

Here are some examples of mapc in action.

```
;; Map the (implicit) composition of two functions
user> (mapc sq inc (range 1 6))
(4 9 16 25 36)
;; We can compose more than two functions
user> (mapc inc sq inc (range 1 6))
(5 10 17 26 37)
;; Or use mapc like plain old map
user> (mapc sq (range 1 6))
(1 4 9 16 25)
;; Or by providing only functional args, produce a function
user> ((mapc sq inc) (range 1 6))
(4 9 16 25 36)
```

To wrap this up, note that I wanted to come close to something like

`(map f) . (map g) = map (f . g)`

The best I could do was

`(comp (mapp f) (mapp g)) = (mapc f g) `

That’s not half bad. I rather like mapp and mapc. But I genuinely wonder whether anyone else will. Play around with mapp and mapc, let me know what you think.

* Update*: In the comments, MarkusQ pointed out that (comp (mapp f) (mapp g)) = (mapp (comp f g)). In particular,

```
user> ((comp (mapp sq) (mapp inc)) (range 1 6))
(4 9 16 25 36)
user> ((mapp (comp sq inc)) (range 1 6))
(4 9 16 25 36)
```

MarkusQ’s equation preserves symmetry by using mapp on both side of the equals sign. I think this is much prettier than the version I came up with. Keats observed that “Beauty is truth, truth beauty…”. The version Markus sent in makes me believe that mapp may well be a worthwhile abstraction.

ML predates Miranda and had nearly identical syntax to Haskell. I think I even prefer o over . since it looks more like the mathematical notation. Looks even better with syntax highlighting :)

val l = [1,2,3,4,5]

fun f x = x * x

fun g x = x + 1

((map f) o (map g)) l (* [4,9,16,25,36] *)

map (f o g) l (* [4,9,16,25,36] *)

May 23, 2011 @ 9:28 am

Interesting. Part of the beauty of the original (to me) is its symmetry. For that reason, I’d favour something like:

(comp (mapp f) (mapp g)) = (mapp (comp f g))

…where the same operations are used on both sides.

— MarkusQ

May 23, 2011 @ 9:40 am

Markus,

I like that a lot. Your point about symmetry is spot on. Thanks.

Brian,

As you point out, both ML and Haskell’s notation were borrowed from mathematics, and a good notation is a thing of beauty. I like this quote from A. N. Whitehead:

BTW, see you tomorrow night at Trifunc.

May 23, 2011 @ 1:31 pm