Reputation: 69
I want get the total distance of a given list, that contains tuples of Floats. I have to guarantee that a list with less than 2 elements is going to output 0.0
What i did so far was this:
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
so the outputs i´m expecting is
ghci> distancia [(0,0), (0,0), (1,0), (1,10)]
11.0
ghci> distancia [(1,1), (3,4)]
3.6055512
but im getting the following error:
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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I don't understand why i have to match the type (Float,Float)
Upvotes: 1
Views: 116
Reputation: 69
So i was trying to come up with a way to use foldl, because on this function i really have to use a foldl or foldr. But i can't get all the examples working
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))
I'm getting a wrong input when a list begins with [(0,0),(0,0)], it always gives me a wrong input, but if the list begins with [(0,0),(1,0),(0,0)] it works.
*Main> distancia [(0,0), (0,0), (1,0), (1,10)]
0,0
but if i do this
*Main> distancia [(0,0), (1,0), (0,0), (1,10)]
3,0
but when use this examples it works
*Main> distancia [(0,0), (1,1), (0,0), (-1, -1), (0,0)]
5.656854
*Main> distancia [(1,1), (0,0)]
1.4142135
What is wrong?
Upvotes: 0
Reputation: 26191
Folding, even if it feels like a reasonable approach, is not the right tool for this particuluar case since to calculate an accumulator value you need two items from the list at once along with the accumulator itself. This is not possible so no folding.
Could be done like;
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
Upvotes: 4