views:

168

answers:

1

Hello, I´ve written a function in Haskell that takes three points in the plane, and checks if they´re on a straight line, or make a right or left turn.

Here´s the code:

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

I´ve tested collinear1, angle, turnAtP in GHCi, and they all terminate immediately. detDirection, however, keeps running forever.

Can someone tell me where the problem here is?

+15  A: 

In Haskell, let is a recursive binding, that is, you can refer to variables declared in the let expression in the defining expressions of the other variables. So, when you write

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

the x1, x2, y1, and y2 on the first line do not refer to the function arguments but to the same names declared later on in the let expression. Just change the two Point lines to bind some different variables, like

        (Point (x3, y3))    = turnAtP a b angleAbX
        (Point (x4, y4))    = turnAtP a c angleAbX

and modify your later computation accordingly, and your infinite looping will go away.

jk
Thank you very much,I can´t believe I actually shadowed my function arguments without noticing.....Next time I´ll use the warnings in GHCi!
Ben