Haskell中的简单链表循环检测

时间:2016-12-11 18:19:28

标签: algorithm haskell functional-programming

我试图在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

1 个答案:

答案 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部分。