5

我在 Haskell 中编写了一个函数,它在平面上取三个点,并检查它们是否在直线上,或者右转或左转。

这是代码:

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

我已经在 GHCi 中测试了collinear1, angle,turnAtP并且它们都立即终止。 detDirection但是,它会一直运行下去。

有人能告诉我这里的问题出在哪里吗?

4

1 回答 1

15

在 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

并相应地修改您以后的计算,您的无限循环将消失。

于 2010-01-24T23:11:55.887 回答