Расстояние между точками на Haskell - PullRequest
3 голосов
/ 17 октября 2019

Я новичок в Haskell, и мне нужно сделать функцию, которая берет список и вычисляет расстояние рекурсивно.

For example:
distance [(0,0),(2,0),(2,5)]
->7
distance [(1,1),(3,4)]
->3.6055512

Я сделал расстояние между двумя точками вот так

distance (x1 , y1) (x2 , y2) = sqrt 
(x'*x' + y'*y')
where
  x' = x1 - x2
  y' = y1 - y2

Но не знаю, как это сделать с переменным размером списка, спасибо

Ответы [ 3 ]

3 голосов
/ 17 октября 2019

Мы можем переименовать эту функцию в distance2, чтобы указать, что она вычисляет расстояние между двумя точками:

distance2 :: Floating a => (a, a) -> (a, a) -> a
distance2 (x1 , y1) (x2 , y2) = sqrt (x'*x' + y'*y')
    where x' = x1 - x2
          y' = y1 - y2

Далее мы можем использовать zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] для одновременной итерации по двум спискам и применения функции к элементам. Здесь мы перебираем список и его хвост. Таким образом, будет получен список расстояний. Мы можем использовать sum :: (Num a, Foldable f) => f a -> a для суммирования этих расстояний:

distance2 :: Floating a => [(a, a)] -> a
distance [] = 0
distance xa@(_:xs) = sum (zipWith distance2 xa xs)
2 голосов
/ 17 октября 2019

Во-первых, как и @WillemVanOnsem, я переименую distance в distance2:

distance2 :: Floating a => (a, a) -> (a, a) -> a
distance2 (x1 , y1) (x2 , y2) = sqrt (x'*x' + y'*y')
    where x' = x1 - x2
          y' = y1 - y2

Далее, если задан список, функция разбить его на пары:

splitPairs :: [a] -> [(a,a)]
splitPairs (x:y:xs) = (x,y) : (splitPairs (y:xs))
splitPairs _ = error "can’t split into pairs when <2 elements!"

Наконец, учитывая список точек, разбейте его на пары, рассчитайте расстояние между каждой парой и сложите их:

distance :: Floating a => [(a,a)] -> a
distance = sum . map (uncurry distance2) . splitPairs
1 голос
/ 17 октября 2019

Без рекурсии лучше всего использовать функции zipWith и sum с аппликативным оператором <*>.

Prelude> :{
Prelude| dist :: Floating a => [(a, a)] -> a
Prelude| dist = sum . (ds <*> tail)
Prelude|        where ds = zipWith (\f s -> sqrt ((fst f - fst s)^2 + (snd f - snd s)^2))
Prelude| :}
Prelude> dist [(0,0),(2,0),(2,5)]
7.0
Prelude> dist [(1,1),(3,4)]
3.605551275463989
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...