【问题标题】:Strange Haskell/GHCi issue奇怪的 Haskell/GHCi 问题
【发布时间】:2025-12-08 07:35:01
【问题描述】:

所以我有一些代码*,当取三点时,应该返回一个方向。我已经编写了这个解决方案,但是每次我尝试运行它时,都会导致 GHCi 冻结,所以我想知道我做错了什么。代码如下:

--chapter 3 question 9
data Point x y = Point x y deriving (Eq, Show)
data Vector x y = Vector x y deriving (Eq, Show)

sub (Point x y) (Point a b) = (Vector (x-a) (y-b))
dot (Vector x y) (Vector a b) = (x*a)+(y*b)
perp (Vector x y) = (Vector (-y) x)
mag (Vector x y) = sqrt (dot v v) where v = (Vector x y)

data Direction = LeftTurn | RightTurn | Straight | Reverse | Stop | Undefined 
    deriving (Eq, Show)
getDirection (Point a b) (Point c d) (Point e f) 
    | a/=c && b/=d && c==e && d==f = Stop
    | a==c && b==d || c==e && d==f || e==a && f==b = Undefined
    | d > 0 = LeftTurn
    | d < 0 = RightTurn
    | otherwise = Straight
    where d = dot (sub p1 p0) (perp (sub p2 p1))
          where p0 = (Point a b)
                p1 = (Point c d)
                p2 = (Point e f)

我看不到递归,所以我不明白为什么它会这样。到目前为止,Haskell 编译器一直非常直言不讳地告诉我什么时候我在做一些愚蠢的事情,但这编译得很好。

*这是“Real World Haskell”第 3 章中的问题 9,如果您想知道的话。

【问题讨论】:

  • 您确定您的数据声明意味着什么,您认为它们是什么意思?目前,您可以有一个 Point [String] (Point, Vector),只是为了命名一个愚蠢的 Point 类型。根据你的用法,声明data Point = Point Int Int deriving(Eq, Show)不是更好吗?

标签: functional-programming ghci haskell


【解决方案1】:

您将名称绑定了两次。首先在Point c d 模式中,而不是在where 子句中。

因此,如果您尝试访问模式绑定的d,实际上是在递归地引用where 子句中的d

【讨论】:

  • 谢谢,我永远也想不通。
  • 如果你使用 -Wall 运行 GHCi,你会收到一个警告。
  • 或者更好的是,将“:set -Wall”行添加到您的 ~/.ghci 文件中。