Функция Haskell не завершается - PullRequest
5 голосов
/ 25 января 2010

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

Вот код:

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 Ответ

15 голосов
/ 25 января 2010

В 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

и соответственно измените ваши более поздние вычисления, и ваш бесконечный цикл исчезнет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...