我正在尝试从循环列表中获取第一个重复元素。例如
[1,-2, 3, 2, 3, 4, 5, 5] => Just 3
[0,-2, 9, 2, 3, 4, -23,- 2] => Just (-2)
v1:
firstDup :: Ord a => [a] -> Maybe a
firstDup [] = Nothing
firstDup (x:xs)
| [x] `intersect` xs == [x] = Just x
| otherwise = firstDup xs
v2:
firstDup' :: Ord a => [a] -> Maybe a
firstDup' = go Set.empty
where
go _ [] = Nothing
go z (x:xs)
| x `Set.member` z = Just x
| otherwise = go (Set.insert x z) xs
我希望v1和v2产生相同的结果,但是它们不会。
firstDup . cycle $ [1,-2, 3, 2, 3, 4, 5, 5] ==> Just 1
firstDup' . cycle $ [1,-2, 3, 2, 3, 4, 5, 5] ==> Just 3
我想知道为什么v1和v2会产生不同的结果。
答案 0 :(得分:5)
请注意谓词
[x] `intersect` xs == [x]
始终为 true ,因为cycle
将列表无限重复为
[1, -2, 3, 2, 3, 4, 5, 5, 1, -2, 3, 2, 3, 4, 5, 5, ...]
和1
必须是[-2, 3, 2, 3, 4, 5, 5, 1, -2, 3, 2, 3, 4, 5, 5, ...]
的元素
如此
[1] `intersect` [-2, 3, 2, 3, 4, 5, 5, 1, -2, 3, 2, 3, 4, 5, 5, ...] = [1]
这就是V1
firstDup
返回Just 1
的原因。
在V2
中,firstDup'
递归构造一个Set:
{}
{1}
{1, -2}
{1, -2, 3}
{1, -2, 3, 2, ...}
并检查下一个插入的元素是否为Set as的元素
1 `Set.member` {}
-2 `Set.member` {1}
3 `Set.member` {1, -2}
2 `Set.member` {1, -2, 3}
3 `Set.member` {1, -2, 3, 2}
请注意,3
是{1, -2, 3, 2}
的成员,因此firstDup'
返回Just 3
。
答案 1 :(得分:3)
在v1
中,它返回列表中第一个元素重复出现在其右自身位置的第一个元素。
在v2
中,它返回列表中第一个在其自身的左某处重复的元素。
在循环列表中,第一个元素将始终在右侧某处重复,因此v1
将始终返回第一个元素。同时,v2
等到之前已经看到一个元素。