使用折叠的总距离

blu*_*fxD 1 haskell tuples fold

我想得到给定列表的总距离,其中包含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
Run Code Online (Sandbox Code Playgroud)

所以我期望的输出是

ghci> distancia [(0,0), (0,0), (1,0), (1,10)]
11.0
ghci> distancia [(1,1), (3,4)]
3.6055512
Run Code Online (Sandbox Code Playgroud)

但是我收到以下错误:

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
  |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

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

Red*_*edu 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
Run Code Online (Sandbox Code Playgroud)