algorithm - Haskell中的简单链表循环检测

标签 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

最佳答案

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

关于algorithm - Haskell中的简单链表循环检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41089463/

相关文章:

algorithm - 博弈论算法: how to proceed

c - 查找满足 i < j 且 A[i]**A[j] > A[j]**A[i] 的对 (A[i], A[j]) 的数量

windows - Windows 上两个网络套接字之间的管道数据

arrays - C 中数组的快速累积和

有效绘制一组线的算法

haskell - 在 Haskell quasiquoter 中拼接任意表达式

haskell - 我应该如何缩进嵌套的 case 表达式?

haskell - 如何使用 `zipTree` 实现 `foldTree` ?

functional-programming - 什么是执行顺序以及它如何影响代码?

Scala 设置匹配案例