Working with the State monad in Haskell
collectUntil :: (s -> Bool) -> State s a -> State s [a] collectUntil f s = do s0 <- get let (a,s') = runState s s0 put s' if (f s') then return [a] else liftM (a:) $ collectUntil f s
これはliftM使いすぎでbind使わなさすぎなコードらしく、次のようになおされてた。
collectUntil2 :: MonadState t m => (t -> Bool) -> m a -> m [a] collectUntil2 f s = do s' <- get if f s' then return [] else do x <- s xs <- collectUntil2 f s return (x:xs)
確かにこっちのほうが(State s)の配管を引っ張りだしてなくて見やすいかもなぁと思いつつ、bindを明示的に書いてみた。
collectUntil3 :: MonadState t m => (t -> Bool) -> m a -> m [a] collectUntil3 f s = get >>= \s' -> if f s' then return [] else s >>= \x -> collectUntil3 f s >>= \xs -> return (x:xs)
参考