代码之家  ›  专栏  ›  技术社区  ›  Materia Gravis

Haskell中基于状态筛选列表

  •  0
  • Materia Gravis  · 技术社区  · 1 年前

    我一直在研究ListT的实现,以找到一种很好的方法来做这样的事情:

    func list = do
      set <- get -- Data.Set
      el <- list
      guard $ Set.notMember el set
      return el
    

    我知道我可以使用ListT.fromFoldable,但我希望能够将此流用作更大的处理管道的一部分,而无需在每一步都从列表转换到流并返回。也许是这样的:

    func' list = (ListT.toReverseList . ListT.take 5 . func . ListT.fromFoldable) list
    

    据我所知,这里应该使用流媒体方法。但我不明白如何使用例如 list-t package 。遍历能以某种方式从流中过滤出结果吗?我没有看到有人问这个问题,所以也许这种方法本身是有缺陷的?

    1 回复  |  直到 1 年前
        1
  •  0
  •   effectfully    1 年前

    编辑前回答原始问题:

    据我所知,这里应该使用流媒体方法。但我不明白如何使用例如 list-t 包裹

    如果你的monad足够懒惰,你可以使用常规列表:

    import Control.Monad (filterM)
    import Control.Monad.Trans.State.Lazy (State, get)
    import Data.Set (Set, member)
    
    filterStateLazy :: Ord a => [a] -> State (Set a) [a]
    filterStateLazy = filterM $ \x -> do
        s <- get
        pure $ x `member` s
    
    -- >>> import Control.Monad.Trans.State.Lazy (evalState)
    -- >>> import qualified Data.Set as Set
    -- >>> take 5 . evalState (filterStateLazy [1..]) $ Set.fromList [1, 6, 22, 39, 54]
    -- [1,6,22,39,54]
    

    如果你真的想 ListT 不过,您也可以使用它,并且不需要懒惰的monad:

    {-# LANGUAGE FlexibleContexts #-}
    {-# LANGUAGE LambdaCase #-}
    
    import ListT
    import Control.Monad.State.Strict
    import Data.Set (Set, member)
    
    filterStateLazy :: (MonadState (Set a) m, Ord a) => ListT m a -> ListT m a
    filterStateLazy (ListT run) = ListT $ run >>= \case
        Nothing -> return Nothing
        Just (x, rest) -> do
            s <- get
            if x `member` s
                then pure $ Just (x, filterStateLazy rest)
                else uncons $ filterStateLazy rest
    
    -- >>> import Control.Monad.Trans.State.Lazy (evalState)
    -- >>> import qualified ListT as ListT
    -- >>> import qualified Data.Set as Set
    -- >>> evalState (ListT.toList . ListT.take 5 . filterStateLazy $ ListT.fromFoldable [1..]) $ Set.fromList [1, 6, 22, 39, 54]
    -- [1,6,22,39,54]
    
    推荐文章