5

Haskellで、平面内の3つのポイントを取り、それらが直線上にあるかどうか、または右または左に曲がるかどうかをチェックする関数を作成しました。

コードは次のとおりです。

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が、すべてすぐに終了します。 ただし、永久に実行され続けます。angleturnAtPdetDirection

誰かがここの問題がどこにあるか教えてもらえますか?

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

最初の行x1x2、、、、y1およびy2は関数の引数を参照していませんが、let式の後半で宣言されている同じ名前を参照しています。2Point行を変更して、次のようないくつかの異なる変数をバインドするだけです。

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

それに応じて後の計算を変更すると、無限ループがなくなります。

于 2010-01-24T23:11:55.887 に答える