使用折叠的总距离

问题描述 投票:1回答:2

我想要获得给定列表的总距离,该列表包含Floats元组。我必须保证少于2个元素的列表将输出0.0

我到目前为止所做的是:

distancia :: [(Float,Float)] -> Float
distancia [] = 0.0
distancia [(_,_)] = 0.0
distancia (x:y:xs) = foldl(\(xa,ya)(xb,yb) -> sqrt(((xa-xb)**2)+((ya-yb)**2))) 0 xs

所以我期望的输出是

ghci> distancia [(0,0), (0,0), (1,0), (1,10)]
11.0
ghci> distancia [(1,1), (3,4)]
3.6055512

但是我收到以下错误:

t3_fc42035.hs:9:22: error:
    * Couldn't match expected type `Float'
                  with actual type `(Float, Float)'
    * In the expression:
        foldl
          (\ (xa, ya) (xb, yb) -> sqrt (((xa - xb) ** 2) + ((ya - yb) ** 2)))
          0
          xs
      In an equation for `distancia':
          distancia (x : y : xs)
            = foldl
                (\ (xa, ya) (xb, yb) -> sqrt (((xa - xb) ** 2) + ((ya - yb) ** 2)))
                0
                xs
  |
9 | distancia (x:y:xs) = foldl(\(xa,ya)(xb,yb) -> sqrt(((xa-xb)**2)+((ya- yb)**2))) 0 xs
  |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

t3_fc42035.hs:9:47: error:
    * Couldn't match expected type `(Float, Float)'
                  with actual type `Float'
    * In the expression: sqrt (((xa - xb) ** 2) + ((ya - yb) ** 2))
      In the first argument of `foldl', namely
        `(\ (xa, ya) (xb, yb)
            -> sqrt (((xa - xb) ** 2) + ((ya - yb) ** 2)))'
      In the expression:
        foldl
          (\ (xa, ya) (xb, yb) -> sqrt (((xa - xb) ** 2) + ((ya - yb) ** 2)))
      0
      xs
  |
9 | distancia (x:y:xs) = foldl(\(xa,ya)(xb,yb) -> sqrt(((xa-xb)**2)+((ya-yb)**2))) 0 xs
  |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我不明白为什么我必须匹配类型(Float,Float)

haskell tuples fold
2个回答
5
投票

即使感觉很合理,折叠也不是这种特殊情况的正确工具,因为要计算累加器值,您需要同时从累加器列表中同时从列表中选择两项。这是不可能的,所以不能折叠。

可以完成;

Prelude> :{
Prelude| let dist = sum . (zipWith hypot <*> tail)
Prelude|            where hypot = \(a,b) (c,d) -> sqrt((a-c)^2 + (b-d)^2)
Prelude| :}
Prelude> dist [(0,0), (0,0), (1,0), (1,10)]
11.0
Prelude> dist [(1,1), (3,4)]
3.605551275463989

0
投票

因此,我试图提出一种使用foldl的方法,因为在此功能上,我确实必须使用foldl或foldr。但我无法使所有示例正常工作

distancia :: [(Float,Float)] -> Float
distancia [] = 0.0
distancia [(_,_)] = 0.0
distancia (x:y:xs) = foldl(\acc -> acc + (hypo x y)) 0 (y:xs)
 where
  hypo (xa,ya)(xb,yb) =  sqrt (((xa-xb)**2)+((ya-yb)**2))

当列表以[[0,0),(0,0)]开头时输入错误,它总是给我一个错误的输入,但是如果列表以[(0,0),(( 1,0),(0,0)]有效。

*Main> distancia [(0,0), (0,0), (1,0), (1,10)]
0,0

但是如果我这样做

*Main> distancia [(0,0), (1,0), (0,0), (1,10)]
3,0

但是使用此示例时,它可以工作

*Main> distancia [(0,0), (1,1), (0,0), (-1, -1), (0,0)]
5.656854

*Main> distancia [(1,1), (0,0)]
1.4142135

怎么了?

© www.soinside.com 2019 - 2024. All rights reserved.