【问题标题】:Haskell function does not terminateHaskell 函数不会终止
【发布时间】:2011-01-08 21:53:23
【问题描述】:

我在 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 中测试了collinear1angleturnAtP,它们都立即终止。 但是,detDirection 会一直运行下去。

谁能告诉我问题出在哪里?

【问题讨论】:

  • 试过逐行遍历它吗?
  • 打开警告(GHCi 中的:set -Wall),您会清楚地看到您做错了什么。

标签: haskell terminate


【解决方案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

第一行的x1x2y1y2 不是指函数参数,而是指稍后在let 表达式中声明的相同名称。只需更改两个Point 行以绑定一些不同的变量,例如

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

并相应地修改你以后的计算,你的无限循环就会消失。

【讨论】:

  • 非常感谢,我不敢相信我居然在没有注意到的情况下隐藏了我的函数参数.....下次我将在 GHCi 中使用警告!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-29
相关资源
最近更新 更多