haskell - 如何在 Haskell 中有效地过滤一对列表?

标签 haskell

我正在解决 Programming Praxis 上的一个简单问题:从列表中删除所有重复项而不更改顺序。假设元素位于 Ord 类中,我得出以下结论:

import Data.Set (Set)  
import qualified Data.Set as Set

buildsets::Ord a => [a] -> [Set a]
buildsets = scanl (flip Set.insert) Set.empty

nub2::Ord a => [a] -> [a]
nub2 thelist = map fst $ filter (not . uncurry Set.member) (zip thelist (buildsets thelist))

正如您所看到的,buildsets 函数让我完成了大部分工作,但是将所有内容放在一起的最后一步(nub2)看起来非常糟糕。有没有更干净的方法来实现这一点?

最佳答案

由于我们必须过滤列表,并且我们可能应该使用一些集合来保存记录,因此我们不妨将 filterM 与状态 monad 一起使用:

import qualified Data.Set as S
import Control.Monad.State.Strict

nub2 :: Ord a => [a] -> [a]
nub2 = (`evalState` S.empty) . filterM go where
    go x = state $ \s -> if S.member x s
        then (False, s)
        else (True, S.insert x s) 

如果我想稍微改进一下这个功能,我会这样做:

import Control.Arrow (&&&)

nub2 = (`evalState` S.empty) . filterM (\x -> state (S.notMember x &&& S.insert x))

关于haskell - 如何在 Haskell 中有效地过滤一对列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20691454/

相关文章:

haskell - 为什么使用 Repa 进行矩阵乘法比使用 hmatrix 更快?

haskell - 带堆栈的阴谋沙盒

python - 这段 Haskell 代码是否等同于这段 Python 代码?

haskell - 状态单子(monad)和 learnyouahaskell.com

haskell - 通过堆栈安装的 LTS 版本

postgresql - Opaleye 新型

parsing - 定点组合器如何使递归构造终止?

haskell - 我怎么知道需要哪个 libstdc++ 双重转换?

configuration - 从 Haskell 查找 X11 屏幕的数量

haskell - 使用 Haskell 重命名文件时如何确保目标文件不存在,以避免覆盖它?