State Monad:修改状态而不修改值

时间:2017-04-04 22:58:10

标签: haskell monads state-monad

我正在编写一个带谓词p和列表的函数。它 返回([value],[state]),其中第一个列表包含传递p的元素,第二个列表包含不传递的元素。但是,当我跑

runState (myFunc even [1,2,3,4,5]) [] 

我得到([2,4,5,3,1],[5,3,1]),其中失败的元素被错误地存储在[value]中。我相信这是由于get更新了状态和值,但是我还没有找到一种方法来更新状态并保留值,所以我想知道如何做到这一点。

myFunc :: (a->Bool) -> [a] -> State [a] [a]
myFunc _ [] = do
  a <- get
  return a
myFunc p (x:xs) = do
    if (p x) then do
      s <- myFunc p xs
      let ret = (x:s)
      return ret
    else do
      s <- get
      put(x:s)
      myFunc p xs

1 个答案:

答案 0 :(得分:2)

您的myFunc _ []定义确实将状态置于值中。你实际上只是希望它是一个空的通行证列表:

myFunc _ [] = return []

然后您可能希望按顺序返回结果:

myFunc :: (a -> Bool) -> [a] -> State [a] [a]
myFunc _ [] = return []
myFunc p (x:xs) = do
    passes <- myFunc p xs

    if p x then
        return (x:passes)
    else do
        modify (x:)
        return passes
尽管它可能是一个状态的练习并且partition已经存在,但是很好的方式来编写它,

import Data.Bifunctor

partition f = foldr m ([], [])
    where m x = (if f x then first else second) (x:)