2010-03-01 13 views
8

有没有办法使用Haskell的“地图”或类似的多个参数?在Haskell中应用于多个参数的地图

即发现和其他点的列表给定的点(定义为一个元组)之间的距离:

map distance (-3,-3) buildings 

显然,这是不行的,因为它试图“距离”映射到(-3,-3),其中距离预计两个元组:

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

距离取两个点作为参数:一个是(-3,-3)在这个例子中,和一个从该列表中“建筑选择”。 (-3,-3)只是一个例子。这必须是一个变量;它不能被硬编码到函数中。

也许这将让更多一点意义:

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. 

回答

10

你想:

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

这是

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

距离取两个点作为参数:一个是(-3,-3)在这个例子中,和一个从该列表“中选择建筑”。 012- (-3,-3)只是一个例子。这必须是一个变量;它不能被硬编码到函数中。 – 2010-03-01 22:10:11

+2

显然“地图(距离第一点)建筑物”将工作,不是吗?或者直截了当地说:“从建筑物建筑物=地图(距离点)建筑物” – ondra 2010-03-01 22:21:29

+0

当然,你可以用一个变量代替(-3,-3)。 – helium 2010-03-01 22:25:33

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

allDistances src dests = map (distance src) dests 

allDistances src = map (distance src) 

allDistances = map . distance 
+2

尼斯扣没有一点点的形式 – 2010-03-01 22:29:09

2

看到在JA的回应我的评论后估计你想用zipWith

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

documentation状态:

zipWith通过用给定的作为第一个参数的函数压缩和解可以推广代替几倍功能拉链。例如,zipWith(+)应用于两个列表以生成相应总和的列表。

因此,在你上面的代码,这可能是这样的:

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] 
0
distance (x, y) (z, w) = sqrt $ (x - z)^2 + (y - w)^2 

func1 = map . distance 

func2 starts ends = starts >>= flip func1 ends 

FUNC1是您所描述的功能,而FUNC2是相似的,但在多重启动点,而不是只取一个,发现了每个组合与终点之间的距离。

0

的距离公式是直接的:

distance :: Floating a => (a,a) -> (a,a) -> a 
distance (x1,y1) (x2,y2) = sqrt $ (x2 - x1)^2 + (y2 - y1)^2 

注意使用模式匹配,以分解的参数,而不是与fstsnd乱扔的代码。

从给定的点到列表中的所有点的各个距离是那么

distanceFrom :: Floating a => (a,a) -> [(a,a)] -> [a] 
distanceFrom p = map (distance p) 

虽然论据似乎丢失,这是在Haskell说法称为partial application。在distanceFrom,我们有两个:

  1. distance p是一个点的功能,它的值是从p
  2. map (distance p)点的距离为中心,其值的列表的功能是这些点各自的距离从p

尝试设计您的Haskell函数的部分应用程序,以便轻松地将小函数组合成更大的函数。如ephemient's answer中所述,您可以进一步获得pointfree定义(无明确参数) - 更优雅,更高级的风格。

到每个点在buildings从所有点在lPoints的距离然后

main :: IO() 
main = do 
    mapM_ (putStrLn . unwords . map (printf "%6.3f")) score 
    where 
    score = [ distanceFrom x buildings | x <- lPoints ] 

例如,制造lPointsbuildings相等,则输出是

 0.000 3.162 5.385 5.099 1.414 
3.162 0.000 3.606 2.828 2.828 
5.385 3.606 0.000 1.000 4.123 
5.099 2.828 1.000 0.000 4.000 
1.414 2.828 4.123 4.000 0.000

但是,这是在一个小镗孔这种特殊情况给予了所有的冗余。为了代替打印strict upper triangle,使用

strictUpperTriangle :: [[a]] -> [[a]] 
strictUpperTriangle [] = [] 
strictUpperTriangle xs = go (init xs) 
    where go (x:xs) = tail x : map tail (go xs) 
     go [] = [] 

printSUT :: PrintfArg a => [[a]] -> IO() 
printSUT sut = putStr (unlines $ map pad sut) 
    where n = length sut 
     pad xs = let k = n - length xs in 
       unwords $ take k blanks ++ map (printf "%*.3f" w) xs 
     blanks = repeat (take w $ repeat ' ') 
     w = 6 :: Int 

main :: IO() 
main = printSUT tri 
    where 
    score = [ distanceFrom x buildings | x <- lPoints ] 
    tri = strictUpperTriangle score 

输出:

 3.162 5.385 5.099 1.414 
     3.606 2.828 2.828 
       1.000 4.123 
         4.000
+0

我不明白这是什么意思?这只是多余的,如果lPpoints和建筑物是平等的 – 2010-03-02 05:03:13

+0

@trinithis在我的脑海中的“在这种情况下”没有让我的答案。谢谢并编辑! – 2010-03-02 15:00:24