Функция Хаскелла не завершается
Я написал функцию в Хаскеле, которая принимает три точки на плоскости, и проверяет, находятся ли они на прямой линии, или делают правый или левый поворот.
Вот код:
detDirection :: Point -> Point -> Point -> Direction
detDirection a@(Point (x1, y1)) b@(Point (x2, y2)) c
= if (collinear1 a b c)
then Straight
else let
ab = Vector [x2 - x1, y2 - y1]
angleAbX = angle ab (Vector [1, 0])
(Point (x1, y1)) = turnAtP a b angleAbX
(Point (x2, y2)) = turnAtP a c angleAbX
in if (y1 > y2)
then Right
else Left
Я проверил collinear1
, angle
, turnAtP
в GHCi, и все они немедленно заканчиваются.
detDirection
, однако, продолжает бежать вечно.
1 ответ:
В Haskell,
let
является рекурсивной привязкой, то есть вы можете ссылаться на переменные, объявленные в выраженииlet
в определяющих выражениях других переменных. Итак, когда вы пишетеlet ab = Vector [x2 - x1, y2 - y1] angleAbX = angle ab (Vector [1, 0]) (Point (x1, y1)) = turnAtP a b angleAbX (Point (x2, y2)) = turnAtP a c angleAbX
x1
,x2
,y1
, иy2
в первой строке ссылаются не на аргументы функции, а на те же имена, объявленные позже в выраженииlet
. Просто измените две строкиPoint
, чтобы связать несколько различных переменных, например(Point (x3, y3)) = turnAtP a b angleAbX (Point (x4, y4)) = turnAtP a c angleAbX
И измените ваши последующие вычисления соответственно, и Ваша бесконечная петля исчезнет.