7

Let's say I have a list of functions

functions = [f, g, h]

each one with type a -> a

I also have a list of values, say numbers but anything should work here

vals = [1,2,3]

I want to apply each function in functions to the corresponding value in vals

My first instinct is to use a lambda and zipWith like:

zipWith (\f v -> f v) functions vals

But frankly this looks ugly and not something I'd expect in such a nice language like Haskell. A function application function sounds like the solution. Is there such a thing? Am I missing something and there is a much nicer solution to my problem? I actually ended-up writing this construct for a Project Euler solution. It works, but I don't like it.

3 Answers 3

16
zipWith ($) f v

$ is function application. The fact that it has particularly low precedence throws people for a loop sometimes.

Sign up to request clarification or add additional context in comments.

Comments

11

Strangely enough,

zipWith id functions vals

will work too!

But, really, zipWith ($) is the right way to write this.

2 Comments

@JuanPablo Because $ is really just id, specialised to only work on functions (and given a very low precedence and an infix notation). The type of $, given that it applies a function to an argument, has to be (a -> b) -> a -> b. Remembering that all Haskell functions are "really" unary (or equivalently that -> associates to the right), that the same type as (a -> b) -> (a -> b). Which means it takes a function of any type and gives you a function of the same type; just a special case of id :: a -> a which takes a value of any type and gives you a value of the same type.
Another way to look at it: using zipWith id means that each resulting element is computed by id f v, and id f equals f so id f v equals f v.
3

Here's another option which might make you think a bit.

>>> import Control.Applicative
>>> let functions = ZipList [(+1), (*2), (*10)]
>>> let values    = ZipList [1, 2, 3]
>>> getZipList (functions <*> values)
[2, 4, 30]

A ZipList is just a wrapper around a list. The definition of <*> for a ZipList says "zip the list of functions (on the left) with the list of arguments (on the right) by applying each function to an argument in turn".

This is in contrast to the definition of <*> for a regular list, which says "take every possible pair of (function, argument) from these two lists and apply the function to the argument".

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.