奇怪的Haskell/GHCi问题

5

我有一段代码,当给定三个点时,应该返回一个方向。我已经编写了这个解决方案,但每次尝试运行它时,都会导致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个问题。


1
你确定你的数据声明意味着你认为它们意味着什么吗?目前,你可能有一个Point [String] (Point, Vector),只是为了命名一个愚蠢的Point类型。根据你的使用情况,声明数据Point = Point Int Int deriving (Eq, Show)不是更好吗? - Boris
1个回答

7

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

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


谢谢,我永远也想不到那个。 - horatius83
5
如果你在运行 GHCi 时使用 -Wall 参数,你将会收到一个关于此的警告。 - Sjoerd Visscher
2
甚至更好的做法是将行”:set -Wall”添加到您的~/.ghci文件中。 - Chris Eidhof

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接