Map applied to multiple arguments in Haskell

21,139

Solution 1

you want:

map (distance (-3, -3)) buildings

which is

map f buildings 
  where f = distance (-3, -3)  

Solution 2

allDistances src dests = map (\point -> distance src point) dests

allDistances src dests = map (distance src) dests

allDistances src = map (distance src)

allDistances = map . distance

Solution 3

After seeing the comment on ja's response I'm guessing you wish to use zipWith

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

The documentation states:

zipWith generalises zip by zipping with the function given as the first argument, instead of a tupling function. For example, zipWith (+) is applied to two lists to produce the list of corresponding sums.

So in your code above this could look like:

Prelude> let dist a b = sqrt ( (fst b - fst a) * (fst b - fst a) + (snd b - snd a) * (snd b - snd a) )
Prelude> let buildings = [(1.0,1.0 ), (3.0,3.0 ), (4.0,4.0)]
Prelude> let points = [ (1.2, 2.23), (2.23, 34.23), (324.3, 34.3) ]
Prelude> zipWith dist points buildings
[1.2461540835707277,31.239491032985793,321.7299799521332]
Share:
21,139
Jason B
Author by

Jason B

Updated on July 09, 2022

Comments

  • Jason B
    Jason B almost 2 years

    Is there a way to use Haskell's "map" or something similar with multiple arguments?

    i.e. to find the distance between a given point (defined as a tuple) and a list of other points:

    map distance (-3,-3) buildings
    

    Clearly, that doesn't work, because it tries to map "distance" to (-3,-3), where distance expects two tuples:

    let distance pointA pointB = sqrt ( (frst pointB - frst pointA) * (frst pointB - frst pointA) + (scnd pointB - scnd pointA) * (scnd pointB - scnd pointA) )
    

    distance takes two points as arguments: one is (-3,-3) in this example, and one is selected from the list "buildings".

    (-3,-3) is just an example. This will have to be a variable; it can't be hardcoded into the function.

    Maybe this will make a little more sense:

    buildings = [(3,-2),(2,1),(5,3),(4,3),(4,-1)]
    
    firstDiff pointA pointB = subtract ( fst pointA ) ( fst pointB )
    
    secondDiff pointA pointB = subtract ( snd pointA ) ( snd pointB )
    
    distance pointA pointB = sqrt ( (firstDiff pointA pointB) * (firstDiff pointA pointB) +     (secondDiff pointA pointB) * (secondDiff pointA pointB))
    
    --- What I need to happen here is a list "score" to be created by taking all distances from a point in a list lPoints to a point in list buildings.
    
  • Jason B
    Jason B about 14 years
    distance takes two points as arguments: one is (-3,-3) in this example, and one is selected from the list "buildings". (-3,-3) is just an example. This will have to be a variable; it can't be hardcoded into the function.
  • ondra
    ondra about 14 years
    obviously "map (distance firstpoint) buildings" would work, wouldn't it? Or to put it bluntly: "frombuilding point buildings = map (distance point) buildings"
  • Jason B
    Jason B about 14 years
    My mistake, it turns out a bug in my distance function was throwing an error; fixing it allowed this to work quite well. Thanks!
  • Nico
    Nico about 14 years
    you might also need to throw a fromIntegral in: distance pointA pointB = (sqrt.fromIntegral) ( (frst pointB - frst pointA) * (frst ...
  • Jason B
    Jason B about 14 years
    That's exactly what wound up fixing it
  • Thomas Eding
    Thomas Eding about 14 years
    I don't get it. What's the point of printing things like that? It is only redundant if lPpoints and buildings are equal.
  • Greg Bacon
    Greg Bacon about 14 years
    @trinithis The "in this case" that was in my head didn't make it to my answer. Thanks and edited!