state monad transformer that adds or combines state

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

state monad transformer that adds or combines state

Dennis Raddle
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.
Reply | Threaded
Open this post in threaded view
|

Re: state monad transformer that adds or combines state

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.
Reply | Threaded
Open this post in threaded view
|

Re: state monad transformer that adds or combines state

Vanessa McHale
In reply to this post by Dennis Raddle

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
Twitter: @vamchale
PGP Key ID: 4209B7B5

Input
          Output

Twitter Github LinkedIn

_______________________________________________
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.

signature.asc (499 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: state monad transformer that adds or combines state

Dennis Raddle
In reply to this post by Francesco Ariis
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 <[hidden email]> 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.
Reply | Threaded
Open this post in threaded view
|

Re: state monad transformer that adds or combines state

Dennis Raddle
In reply to this post by Vanessa McHale


On Tue, May 15, 2018 at 7:08 AM, Vanessa McHale <[hidden email]> wrote:

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



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


_______________________________________________
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.
Reply | Threaded
Open this post in threaded view
|

Re: state monad transformer that adds or combines state

Vanessa McHale
In reply to this post by Dennis Raddle

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 <[hidden email]> 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.

signature.asc (499 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: state monad transformer that adds or combines state

Ryan Reich
In reply to this post by Dennis Raddle
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 <[hidden email]> 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 <[hidden email]> 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.
Reply | Threaded
Open this post in threaded view
|

Re: state monad transformer that adds or combines state

Will Yager

On May 15, 2018, at 17:39, Ryan Reich <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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.

_______________________________________________
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.
Reply | Threaded
Open this post in threaded view
|

Re: state monad transformer that adds or combines state

Alexis King
In reply to this post by Dennis Raddle
> On May 15, 2018, at 16:29, Dennis Raddle <[hidden email]>
> 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

_______________________________________________
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.