0

I'm making a function that does

(a->Bool) -> [a] -> State [a] [a]

and I was wondering if there was a simple way to go through the list storing "failed" items that didn't pass the predicate as the state and the "passing" items as the value that will eventually be returned? You would see both the return value and the state. Samples:

*CL> runState (func (<3) [1, 2, 3]) []
([1, 2], [3])
*CL> runState (func even [1, 2, 3]) [10]
([2], [10, 1, 3])

I've looked long and hard for answers and haven't found anything on this specific situation yet. I know I can do it differently as I have, but I specifically want to know if I can do it in the way mentioned above.

2 Answers2

4

You don't really need to use state for this since you could return a pair of (passed, failed) but you can do:

partitionSt :: (a->Bool) -> [a] -> State [a] [a]
partitionSt f l = do
  let (passed, failed) = partition f l
  s <- return passed
  put failed
  return s

or

partitionSt f l = return passed <* (put failed)
  where (passed, failed) = partition f l
Lee
  • 142,018
  • 20
  • 234
  • 287
  • I can't do let (passed, failed) = partitionSt f l since it's State [a] [a] – DogOnKeyboard Apr 05 '15 at 16:37
  • Didn't exactly answer my question, but you did put me on the right track by showing me I could bind the return. Thanks – DogOnKeyboard Apr 05 '15 at 17:02
  • The first approach can be streamlined, because `return passed` doesn't do anything. Just skip that line and use `put failed; return passed` – dfeuer Apr 05 '15 at 21:17
0

Alright I figured it out. I'm supposed to bind both the return value and the next iteration of the state and return that, otherwise just updating the state and iterating through. Lee did put me on the right track by showing me I could bind the return value.