state monad transformer that adds or combines state

I find myself using the state and exception monads at large scale in my programs. For instance I often keep a pseudorandom generator as the state, and use exception handling. In local computations, I may want to use some additional state. Is there a way to add a little extra state temporarily? Let's say I have data State1 = State1 StdGen type M1 = State State1 data State2 = State2 State1 Int type M2 = State State2 runM2 :: M2 a -> Int -> M1 a someFunc :: M1 Double someFunc = do r <- <compute something pseudorandomly> r2 <- runM2 (deeperFunc r) 3 <..etc..> deeperFunc :: Double -> M2 Double

On Mon, May 14, 2018 at 10:27:19PM -0700, Dennis Raddle wrote:
In local computations, I may want to use some additional state. Is there a way to add a little extra state temporarily?
Would StateT work (in general, taking advantage of what transformers have to offer)?

I'm not sure what happens if I apply a StateT to an existing State or
StateT monad. Not sure how 'get' and 'put' would function, or if I would
need to lift get and put to choose which state to access.
D
On Tue, May 15, 2018 at 12:49 AM, Francesco Ariis
On Mon, May 14, 2018 at 10:27:19PM -0700, Dennis Raddle wrote:
In local computations, I may want to use some additional state. Is there a way to add a little extra state temporarily?
Would StateT work (in general, taking advantage of what transformers have to offer)? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

You can apply StateT to an existing monad, e.g. StateT StateType (Either ErrorType). Then 'get' and 'put' can be used inside this monad. On 05/15/2018 04:29 PM, Dennis Raddle wrote:
I'm not sure what happens if I apply a StateT to an existing State or StateT monad. Not sure how 'get' and 'put' would function, or if I would need to lift get and put to choose which state to access.
D
On Tue, May 15, 2018 at 12:49 AM, Francesco Ariis
mailto:fa-ml@ariis.it> wrote: On Mon, May 14, 2018 at 10:27:19PM -0700, Dennis Raddle wrote: > In local computations, I may want to use some additional state. Is there a > way to add a little extra state temporarily?
Would StateT work (in general, taking advantage of what transformers have to offer)? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

You can use plain get and put to interact with the outer state, and you
have to apply lift to use the inner state. This problem, which for almost
any other combination of transformers is solved by mtl's web of MonadState
instances, is an example of why the topic of "extensible effects" is so
hot. You are basically asking to add, and later subtract, a new state
"effect". Barring rewriting your original state type as a product that
includes the new one, there isn't really a neat way of doing this.
On Tue, May 15, 2018, 14:29 Dennis Raddle
I'm not sure what happens if I apply a StateT to an existing State or StateT monad. Not sure how 'get' and 'put' would function, or if I would need to lift get and put to choose which state to access.
D
On Tue, May 15, 2018 at 12:49 AM, Francesco Ariis
wrote: In local computations, I may want to use some additional state. Is
On Mon, May 14, 2018 at 10:27:19PM -0700, Dennis Raddle wrote: there a
way to add a little extra state temporarily?
Would StateT work (in general, taking advantage of what transformers have to offer)? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

Check out http://hackage.haskell.org/package/lens-4.16.1/docs/Control-Lens-Zoom.html#v...
On May 15, 2018, at 17:39, Ryan Reich
wrote: You can use plain get and put to interact with the outer state, and you have to apply lift to use the inner state. This problem, which for almost any other combination of transformers is solved by mtl's web of MonadState instances, is an example of why the topic of "extensible effects" is so hot. You are basically asking to add, and later subtract, a new state "effect". Barring rewriting your original state type as a product that includes the new one, there isn't really a neat way of doing this.
On Tue, May 15, 2018, 14:29 Dennis Raddle
wrote: I'm not sure what happens if I apply a StateT to an existing State or StateT monad. Not sure how 'get' and 'put' would function, or if I would need to lift get and put to choose which state to access. D
On Tue, May 15, 2018 at 12:49 AM, Francesco Ariis
wrote: On Mon, May 14, 2018 at 10:27:19PM -0700, Dennis Raddle wrote: In local computations, I may want to use some additional state. Is there a way to add a little extra state temporarily?
Would StateT work (in general, taking advantage of what transformers have to offer)? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

On May 15, 2018, at 16:29, Dennis Raddle
wrote: I'm not sure what happens if I apply a StateT to an existing State or StateT monad. Not sure how 'get' and 'put' would function, or if I would need to lift get and put to choose which state to access.
The immediate answer to this question is “yes”. If you had StateT on top of StateT, you could access the different pieces of state by lifting to the appropriate level. As Ryan points out, this is admittedly a bit awkward, since it doesn’t work with the classes from mtl (due to the functional dependency on MonadState). Still, it’s possible. Extensible effects can solve this a little more cleanly. You can easily handle an effect locally, and you can have multiple state effects with different types. For example, using freer-simple: import Control.Monad.Freer import Control.Monad.Freer.State f :: Member (State StdGen) eff => Eff eff Double f = do r <- <do something pseudorandomly> r2 <- runState @Int 3 (deeperFunc r) <...> deeperFunc :: Members '[State StdGen, State Int] eff => Double -> Eff eff Double deeperFunc = <...> This works just fine. To others suggesting the OP make the state a product: this seems unsatisfactory to me. It means you have to carry around the state for every local computation you might use, even long after it is no longer needed. If the state is truly local, there’s really no need to carry it around after its lifetime is, semantically, over. We invented local variables for a reason. (Such globalization of state also won’t work in general for things like recursive functions, for the same reasons that local variables cannot be properly implemented without a stack.) One small disclaimer: I am the maintainer of freer-simple, though I can’t really claim to be the author, since it’s a fork, and others did the vast majority of the work. Take my bias as you will. Alexis

You can simply use a state monad and then extract the data later when you don't want the extra state, viz. | sum :: (Num a) => [a] -> a sum xs = flip execState 0 $ mapM_ (\x -> do { s <- get ; put $ x + s }) xs |
For instance I often keep a pseudorandom generator as the state, and use exception handling.
I'd use a monad transformer. Either `ExceptT` (which would add exceptions to the state monad) or `StateT` (which would add state to an exception monad). On 05/15/2018 12:27 AM, Dennis Raddle wrote:
I find myself using the state and exception monads at large scale in my programs. For instance I often keep a pseudorandom generator as the state, and use exception handling.
In local computations, I may want to use some additional state. Is there a way to add a little extra state temporarily?
Let's say I have
data State1 = State1 StdGen
type M1 = State State1
data State2 = State2 State1 Int
type M2 = State State2
runM2 :: M2 a -> Int -> M1 a
someFunc :: M1 Double someFunc = do r <- <compute something pseudorandomly> r2 <- runM2 (deeperFunc r) 3 <..etc..>
deeperFunc :: Double -> M2 Double
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- *Vanessa McHale* Functional Compiler Engineer | Chicago, IL Website: www.iohk.io http://iohk.io Twitter: @vamchale PGP Key ID: 4209B7B5 Input Output http://iohk.io Twitter https://twitter.com/InputOutputHK Github https://github.com/input-output-hk LinkedIn https://www.linkedin.com/company/input-output-global

On Tue, May 15, 2018 at 7:08 AM, Vanessa McHale
You can simply use a state monad and then extract the data later when you don't want the extra state, viz.
sum :: (Num a) => [a] -> asum xs = flip execState 0 $ mapM_ (\x -> do { s <- get ; put $ x + s }) xs
Not quite sure how this relates to my point. I need to have modify access to the state in the deeper, original monad, as well as a temporary state monad on top of it. And I don't want to create a single data constructor for a single state monad that has fields for every conceivable use anywhere in my code. D
participants (6)
-
Alexis King
-
Dennis Raddle
-
Francesco Ariis
-
Ryan Reich
-
Vanessa McHale
-
Will Yager