Just came up with two similar mapping functions in Clojure: map-grid and map-tree.

map-grid

Given a regular n-dimensional table of data, apply a function to each cell along with its index path specific to a given depth. For example, with the following 2 dimensional table:

(def table
  [ [0 1 0]
    [0 1 0]
    [0 1 0] ])

To generate a hash-map from locations to data, one might write:

;;  For rows as data:
(apply merge (flatten (map-grid 1 hash-map table)))

;;  Resulting in:
;;  {[1] [0 1 0],
;;   [2] [0 1 0],
;;   [0] [0 1 0]}


;;  For cells as data
(apply merge (flatten (map-grid 2 hash-map table)))

;;  Resulting in:
;;  {[2 1] 1,
;;   [1 0] 0,
;;   [2 2] 0,
;;   [0 0] 0,
;;   [1 1] 1,
;;   [0 1] 1,
;;   [1 2] 0,
;;   [0 2] 0,
;;   [2 0] 0}

map-grid accepts a depth-level a function and some data. The depth-level specifies how deep to traverse the data. The function describes the transformation of a cell with access to the cells index path.

The definition of map-grid is as follows:

(defn map-grid
  ([depth f data] (map-grid depth f data []))
  ([depth f data levels]
    (if (zero? depth)
      (f levels data)
      (map-indexed
        (fn [i v]
          (map-grid (dec depth) f v (conj levels i)))
        data))))

map-tree

This function doesn’t allow for the depth to be specified - if a collection is found, it will iterate through it. Defined as follows:

(defn map-tree
  ([f data] (map-tree f data []))
  ([f data levels]
    (if (coll? data)
      (map-indexed
        (fn [i v]
          (map-tree f v (conj levels i)))
        data)
      (f levels data))))

My point-free implementation of Map in Haskell:

map = (`foldr` []) . ((:) .)

I’ve used a little trick with foldr by specifying just the second parameter. I did this by using it as an infix operator, even though the full signature takes three arguments.

As I understand it; the point-free style is when arguments aren’t named or included at all in the function definition. An alternate definition of map, which uses a “point-full” style (in which the arguments are named) could be written as:

map f xs = foldr ((:) . f) [] xs