我试图在Haskell中实现一个简单的链表......
data List a = Nil | Cons a (List a) deriving (Show, Eq)
...以及它的循环检测算法:
listNext :: List a -> List a
listNext Nil = Nil
listNext (Cons _ xs) = xs
loopDetecting' :: (Eq a) => List a -> List a -> Bool
loopDetecting' current next
| current == Nil || next1 == Nil || next2 == Nil = False
| current == next1 || current == next2 = True
| otherwise = loopDetecting' (listNext current) next2
where
next1 = listNext next
next2 | next1 == Nil = Nil
| otherwise = listNext next1
loopDetecting :: (Eq a) => List a -> Bool
loopDetecting Nil = False
loopDetecting (Cons _ xs) = loopDetecting' xs xs
然而,我得到了无限的递归。有什么问题?
此处的完整代码:https://gist.github.com/mrLSD/03381a277c336c1902f9d78b79a131b0
答案 0 :(得分:4)
| current == next1 || current == next2 = True
此行在两个未知列表上使用==
。要确定两个列表是否相等,==
必须遍历其元素。如果列表是无限的,==
只会在找到差异后返回。如果他们相等,==
永远不会停止。
至于为什么==
执行此操作:您的类型的编译器生成的Eq
实例(由deriving (Eq)
提供)如下所示:
instance (Eq a) => Eq (List a) where
(==) Nil Nil = True
(==) (Cons x xs) (Cons y ys) = x == y && xs == ys
(==) _ _ = False
递归位于xs == ys
部分。