
I'm trying to understand how to use State in a function. I've avoided the topic for several years because State just never seemed very useful, but I figure it's time for me to figure it out: I have the following function
update :: (a -> (r,a)) -> Int -> [a] -> (r, [a]) update s 0 (a:as) = let (r,a') = s a in (r,a':as) update s i (a:as) = let (r,as') = update s (i-1) as in (r, a:as')
which updates a particular element of a list. Looking at it, I see two parts of the type signature that look like State types, which leads me to think of this:
update' :: State a r -> Int -> State [a] r
Which leads to me writing this:
update' s 0 = do (a:as) <- get let (r, a') = runState s a put (a':as) return r update' s i = do (a:as) <- get put as r <- update' s (i-1) as' <- get put (a:as') return r
Now, this just looks awful. The first half, the base condition, is actually "running" a State calculation. And the second half sets the state within the monad twice! I like the idea of using State because it simplifies the type. When I see (a -> (b,a)) I say "Wait a second, that's a State calculation, isn't it?" and then, hopefully, generalize. But I can't write that calculation nearly as concisely. How do I do this properly?