Mapping over multiple lists

1,088 views
Skip to first unread message

Mark Brown

unread,
Feb 15, 2014, 6:18:56 PM2/15/14
to elm-d...@googlegroups.com
I've been interested in functional languages for a couple of years now and started by learning Common Lisp. In CL, the map function and its friends can take an arbitrary number of lists as arguments. Elm is my first ML-style functional language and I'm missing this feature. What do programmers in ML-style languages do to map over several lists?

I wrote a function map2 that does what I want for two lists:

map2 fun alst blst =
  let aux_map acc al bl =
        if (al == [] || bl == [])
           then reverse acc
           else aux_map ((fun (head al) (head bl)) :: acc) (tail al) (tail bl)
  in aux_map [] alst blst

(looks like Lisp, sorry!) but if I want to do the same for 3, 4 or more lists I have to write more functions.

What's the approach in Elm?  It occurs to me that you could do a zip to group list elements into tuples, then map over the list of tuples, but isn't there an efficiency penalty compared to my hand-rolled map2 function?

Is it even possible to have varadic functions (functions that can take variable numbers of arguments) in ML-style languages?

John Mayer

unread,
Feb 15, 2014, 6:27:41 PM2/15/14
to elm-d...@googlegroups.com
That looks like zipWith; it's already in stdlib

zipWith : (a -> b -> c) -> [a] -> [b] -> [c]


--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Max New

unread,
Feb 15, 2014, 8:18:27 PM2/15/14
to elm-d...@googlegroups.com
There is a trick to doing this in a language like Elm/Haskell/ML that only has single argument functions, without using needing zipWith,zipWith3,zipWith4,... by using partial application. You only need 2 functions:

map : (a ->b) -> [a] -> [b]
and
zipApply : [a -> b] -> [a] -> [b]
zipApply xs fs = case (xs, fs) of
  ( f :: fs', x :: xs') -> f x :: zipApply fs' xs'
  _                       -> []

Then if you want to apply a 2-arg function f over lists xs and ys, you could do

zipApply (map f xs) ys

and for 3 args you do

zipApply (zipApply (map f xs) ys) zs

but this gets confusing so we usually do it infix

f `map` xs `zipApply` ys `zipApply` zs

and then at this point it's convenient to define operators. You could define (<~) = map and (~) = zipApply and you'd get

f <~ xs ~ ys ~ zs

And this is exactly the purpose of (<~) and (~) in the Elm stdlib except they are for Signals instead of lists (so you should probably name them something else)!

In Haskell this pattern is reified in the form of Applicative functors: http://www.haskell.org/haskellwiki/Typeclassopedia#Applicative

Max New

unread,
Feb 15, 2014, 8:21:28 PM2/15/14
to elm-d...@googlegroups.com
Though note that in haskell the definition of the applicative functor operations corresponds to taking the cartesian product of lists, not zipping them: http://hackage.haskell.org/package/base-4.6.0.1/docs/Control-Applicative.html#t:ZipList. Also in Haskell, (<~) is called (<$>) and (~) is called (<*>)

Max Goldstein

unread,
Feb 15, 2014, 8:56:22 PM2/15/14
to elm-d...@googlegroups.com
Psst: Diving into Haskell category theory is probably not the best idea for someone with a lisp background. That said, I think Mark will find your first post helpful.

John Mayer

unread,
Feb 15, 2014, 9:55:46 PM2/15/14
to elm-d...@googlegroups.com

I'm pretty sure you can define zipApply as (zipWith (<|)) ?

On Feb 15, 2014 8:56 PM, "Max Goldstein" <maxgol...@gmail.com> wrote:
Psst: Diving into Haskell category theory is probably not the best idea for someone with a lisp background. That said, I think Mark will find your first post helpful.

--

Max New

unread,
Feb 15, 2014, 10:05:18 PM2/15/14
to elm-d...@googlegroups.com

On Sat, Feb 15, 2014 at 8:55 PM, John Mayer <john.p....@gmail.com> wrote:
I'm pretty sure you can define zipApply as (zipWith (<|)) ?

Right

-Max Stewart New

Mark Brown

unread,
Feb 16, 2014, 8:55:51 AM2/16/14
to elm-d...@googlegroups.com

Thanks - I thought there might be a way to do it but I'm new to the ML game. I'll give it a try!

Max New

unread,
Feb 17, 2014, 6:51:59 PM2/17/14
to elm-d...@googlegroups.com
Coincidentally I just read a new paper yesterday that has variable-arity zipWith as an example of what you can do using a new dependent-type feature in Haskell.

I don't suggest reading this if you're new to ML-style type systems, but thought it was a funny coincidence worth mentioning for people who are curious about dependent types.

The paper is https://research.microsoft.com/en-us/um/people/simonpj/papers/ext-f/axioms-extended.pdf and the example is in Appendix B starting on page 14.
Reply all
Reply to author
Forward
0 new messages