Do we have idiom for lifting a state monad into pair of states?

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

Do we have idiom for lifting a state monad into pair of states?

Ahn, Ki Yung
Consider you have developed library routines that act on (State s1 a).
For some reason, you need more than one state simultaneously. Let's say
two side by side for simple example, that is (State (s1,s2) a). To use
library functions on one state monad in a two state monad, we need to
wrapper that lifts actions of (State s1 a) to (State (s1,s2) a).

It is not difficult to write a lifter for such purposes as below. It is
kind of like doing liftA in Applicative libarary, but instead of the
last argument 'a' but on the fist argument 's' of (State s a). This
seems like an idiom that can often come up. So, I tried some searching
in some applicative related libraries and monad transformer related
libraries but haven't found this idiom yet.

If you had a need for idioms like below, what do you call it? Or, is
there a way more general way I've missed that makes this a very special
case of it.

 > import Control.Monad.State
 > import Control.Monad.Error
 > import Control.Applicative
 >
 > -- lift an action over a state into a pair of states
 > --
 > do1st :: State s1 a -> State (s1,s2) a
 > do1st m1 = do (s1, s2) <- get
 >               let (a, s1') = runState m1 s1
 >               put (s1',s2)
 >               return a
 >
 > do2nd :: State s2 a -> State (s1,s2) a
 > do2nd m2 = do (s1, s2) <- get
 >               let (a, s2') = runState m2 s2
 >               put (s1,s2')
 >               return a
 >
 >
 > -- lift an action over a state with error
 > -- into a pair of states with error
 > --
 > do1 :: Error e => ErrorT e (State s1) a -> ErrorT e (State (s1,s2)) a
 > do1 m1 = do (s1, s2) <- lift get
 >             let (ma,s1') = (runState . runErrorT) m1 s1
 >             case ma of
 >               Left e  -> throwError e
 >               Right a -> do lift $ put (s1',s2)
 >                             return a
 >
 >
 > do2 :: Error e => ErrorT e (State s2) a -> ErrorT e (State (s1,s2)) a
 > do2 m2 = do (s1, s2) <- lift get
 >             let (ma,s2') = (runState . runErrorT) m2 s2
 >             case ma of
 >               Left e  -> throwError e
 >               Right a -> do lift $ put (s1,s2')
 >                             return a

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Do we have idiom for lifting a state monad into pair of states?

Roman Cheplyaka-2
It's called 'zoom' in various lens libraries.

On 26/03/15 10:28, Ki Yung Ahn wrote:

> Consider you have developed library routines that act on (State s1 a).
> For some reason, you need more than one state simultaneously. Let's say
> two side by side for simple example, that is (State (s1,s2) a). To use
> library functions on one state monad in a two state monad, we need to
> wrapper that lifts actions of (State s1 a) to (State (s1,s2) a).
>
> It is not difficult to write a lifter for such purposes as below. It is
> kind of like doing liftA in Applicative libarary, but instead of the
> last argument 'a' but on the fist argument 's' of (State s a). This
> seems like an idiom that can often come up. So, I tried some searching
> in some applicative related libraries and monad transformer related
> libraries but haven't found this idiom yet.
>
> If you had a need for idioms like below, what do you call it? Or, is
> there a way more general way I've missed that makes this a very special
> case of it.
>
>> import Control.Monad.State
>> import Control.Monad.Error
>> import Control.Applicative
>>
>> -- lift an action over a state into a pair of states
>> --
>> do1st :: State s1 a -> State (s1,s2) a
>> do1st m1 = do (s1, s2) <- get
>>               let (a, s1') = runState m1 s1
>>               put (s1',s2)
>>               return a
>>
>> do2nd :: State s2 a -> State (s1,s2) a
>> do2nd m2 = do (s1, s2) <- get
>>               let (a, s2') = runState m2 s2
>>               put (s1,s2')
>>               return a
>>
>>
>> -- lift an action over a state with error
>> -- into a pair of states with error
>> --
>> do1 :: Error e => ErrorT e (State s1) a -> ErrorT e (State (s1,s2)) a
>> do1 m1 = do (s1, s2) <- lift get
>>             let (ma,s1') = (runState . runErrorT) m1 s1
>>             case ma of
>>               Left e  -> throwError e
>>               Right a -> do lift $ put (s1',s2)
>>                             return a
>>
>>
>> do2 :: Error e => ErrorT e (State s2) a -> ErrorT e (State (s1,s2)) a
>> do2 m2 = do (s1, s2) <- lift get
>>             let (ma,s2') = (runState . runErrorT) m2 s2
>>             case ma of
>>               Left e  -> throwError e
>>               Right a -> do lift $ put (s1,s2')
>>                             return a
>
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Do we have idiom for lifting a state monad into pair of states?

Fumiaki Kinoshita
In reply to this post by Ahn, Ki Yung
One solution is to use lens package.

The lens package provides an interesting combinator, zoom, in Control.Lens.Zoom[1]:

zoom :: Monad m             => Lens' s t      -> StateT t m a -> StateT s m a

Lens' s a is the type of accessors to `a`. When it comes to tuples, you can use

_1 :: Lens' (a, b) a
_2 :: Lens' (a, b) b

So do1st, do2nd are zoom _1, zoom _2 respectively.

zoom also can be used for monad transformer stacks; zoom _1 may have the type of do1.


2015-03-26 17:28 GMT+09:00 Ki Yung Ahn <[hidden email]>:
Consider you have developed library routines that act on (State s1 a).
For some reason, you need more than one state simultaneously. Let's say two side by side for simple example, that is (State (s1,s2) a). To use library functions on one state monad in a two state monad, we need to wrapper that lifts actions of (State s1 a) to (State (s1,s2) a).

It is not difficult to write a lifter for such purposes as below. It is kind of like doing liftA in Applicative libarary, but instead of the last argument 'a' but on the fist argument 's' of (State s a). This seems like an idiom that can often come up. So, I tried some searching in some applicative related libraries and monad transformer related libraries but haven't found this idiom yet.

If you had a need for idioms like below, what do you call it? Or, is there a way more general way I've missed that makes this a very special case of it.

> import Control.Monad.State
> import Control.Monad.Error
> import Control.Applicative
>
> -- lift an action over a state into a pair of states
> --
> do1st :: State s1 a -> State (s1,s2) a
> do1st m1 = do (s1, s2) <- get
>               let (a, s1') = runState m1 s1
>               put (s1',s2)
>               return a
>
> do2nd :: State s2 a -> State (s1,s2) a
> do2nd m2 = do (s1, s2) <- get
>               let (a, s2') = runState m2 s2
>               put (s1,s2')
>               return a
>
>
> -- lift an action over a state with error
> -- into a pair of states with error
> --
> do1 :: Error e => ErrorT e (State s1) a -> ErrorT e (State (s1,s2)) a
> do1 m1 = do (s1, s2) <- lift get
>             let (ma,s1') = (runState . runErrorT) m1 s1
>             case ma of
>               Left e  -> throwError e
>               Right a -> do lift $ put (s1',s2)
>                             return a
>
>
> do2 :: Error e => ErrorT e (State s2) a -> ErrorT e (State (s1,s2)) a
> do2 m2 = do (s1, s2) <- lift get
>             let (ma,s2') = (runState . runErrorT) m2 s2
>             case ma of
>               Left e  -> throwError e
>               Right a -> do lift $ put (s1,s2')
>                             return a

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Do we have idiom for lifting a state monad into pair of states?

Ahn, Ki Yung
In reply to this post by Roman Cheplyaka-2
Thanks, yes, it should of course been in Lens!!

*Main Control.Lens> :t zoom _1 :: State s1 a -> State (s1,s2) a
zoom _1 :: State s1 a -> State (s1,s2) a
   :: State s1 a -> State (s1, s2) a

*Main Control.Lens> :t zoom _2 :: State s2 a -> State (s1,s2) a
zoom _2 :: State s2 a -> State (s1,s2) a
   :: State s2 a -> State (s1, s2) a

It works beautifully :)




2015년 03월 26일 01:32에 Roman Cheplyaka 이(가) 쓴 글:

> It's called 'zoom' in various lens libraries.
>
> On 26/03/15 10:28, Ki Yung Ahn wrote:
>> Consider you have developed library routines that act on (State s1 a).
>> For some reason, you need more than one state simultaneously. Let's say
>> two side by side for simple example, that is (State (s1,s2) a). To use
>> library functions on one state monad in a two state monad, we need to
>> wrapper that lifts actions of (State s1 a) to (State (s1,s2) a).
>>
>> It is not difficult to write a lifter for such purposes as below. It is
>> kind of like doing liftA in Applicative libarary, but instead of the
>> last argument 'a' but on the fist argument 's' of (State s a). This
>> seems like an idiom that can often come up. So, I tried some searching
>> in some applicative related libraries and monad transformer related
>> libraries but haven't found this idiom yet.
>>
>> If you had a need for idioms like below, what do you call it? Or, is
>> there a way more general way I've missed that makes this a very special
>> case of it.
>>
>>> import Control.Monad.State
>>> import Control.Monad.Error
>>> import Control.Applicative
>>>
>>> -- lift an action over a state into a pair of states
>>> --
>>> do1st :: State s1 a -> State (s1,s2) a
>>> do1st m1 = do (s1, s2) <- get
>>>                let (a, s1') = runState m1 s1
>>>                put (s1',s2)
>>>                return a
>>>
>>> do2nd :: State s2 a -> State (s1,s2) a
>>> do2nd m2 = do (s1, s2) <- get
>>>                let (a, s2') = runState m2 s2
>>>                put (s1,s2')
>>>                return a
>>>
>>>
>>> -- lift an action over a state with error
>>> -- into a pair of states with error
>>> --
>>> do1 :: Error e => ErrorT e (State s1) a -> ErrorT e (State (s1,s2)) a
>>> do1 m1 = do (s1, s2) <- lift get
>>>              let (ma,s1') = (runState . runErrorT) m1 s1
>>>              case ma of
>>>                Left e  -> throwError e
>>>                Right a -> do lift $ put (s1',s2)
>>>                              return a
>>>
>>>
>>> do2 :: Error e => ErrorT e (State s2) a -> ErrorT e (State (s1,s2)) a
>>> do2 m2 = do (s1, s2) <- lift get
>>>              let (ma,s2') = (runState . runErrorT) m2 s2
>>>              case ma of
>>>                Left e  -> throwError e
>>>                Right a -> do lift $ put (s1,s2')
>>>                              return a
>>
>> _______________________________________________
>> Haskell-Cafe mailing list
>> [hidden email]
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>>


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Do we have idiom for lifting a state monad into pair of states?

lennart spitzner
In reply to this post by Ahn, Ki Yung
Let me grab this opportunity to advertise the multistate package [1].

The underlying assumption is that the types of the states in your
stack are distinct. In that case, type inference can give you
something like "automatic zooming" for a MultiState that contains
arbitrary heterogenous lists (tuples).
Generous usage of the Monad(Multi)State type class would thereby
eliminate the need for do1st and do2nd. See the example in the package.

The package does not (yet!) work well with existing transformers, for
example one might think of running a StateT on one of the states in a
MultiStateT. This is not a problem when using MultiStateT exclusively,
but of course bad for interoperability. I am open for specific
requests in that direction.

In the last few days I have been working on adding a MultiRWST, but
this is not completely finished yet (and I am not sure yet how to make
the interface consistent; the whole run/eval/exec distinction seems
unintuitive, especially when you have multiple states..)

Lennart


[1] https://hackage.haskell.org/package/multistate


On 26/03/15 09:28, Ki Yung Ahn wrote:

> Consider you have developed library routines that act on (State s1 a).
> For some reason, you need more than one state simultaneously. Let's
> say two side by side for simple example, that is (State (s1,s2) a). To
> use library functions on one state monad in a two state monad, we need
> to wrapper that lifts actions of (State s1 a) to (State (s1,s2) a).
>
> It is not difficult to write a lifter for such purposes as below. It
> is kind of like doing liftA in Applicative libarary, but instead of
> the last argument 'a' but on the fist argument 's' of (State s a).
> This seems like an idiom that can often come up. So, I tried some
> searching in some applicative related libraries and monad transformer
> related libraries but haven't found this idiom yet.
>
> If you had a need for idioms like below, what do you call it? Or, is
> there a way more general way I've missed that makes this a very
> special case of it.
>
>> import Control.Monad.State
>> import Control.Monad.Error
>> import Control.Applicative
>>
>> -- lift an action over a state into a pair of states
>> --
>> do1st :: State s1 a -> State (s1,s2) a
>> do1st m1 = do (s1, s2) <- get
>>               let (a, s1') = runState m1 s1
>>               put (s1',s2)
>>               return a
>>
>> do2nd :: State s2 a -> State (s1,s2) a
>> do2nd m2 = do (s1, s2) <- get
>>               let (a, s2') = runState m2 s2
>>               put (s1,s2')
>>               return a
>>
>>
>> -- lift an action over a state with error
>> -- into a pair of states with error
>> --
>> do1 :: Error e => ErrorT e (State s1) a -> ErrorT e (State (s1,s2)) a
>> do1 m1 = do (s1, s2) <- lift get
>>             let (ma,s1') = (runState . runErrorT) m1 s1
>>             case ma of
>>               Left e  -> throwError e
>>               Right a -> do lift $ put (s1',s2)
>>                             return a
>>
>>
>> do2 :: Error e => ErrorT e (State s2) a -> ErrorT e (State (s1,s2)) a
>> do2 m2 = do (s1, s2) <- lift get
>>             let (ma,s2') = (runState . runErrorT) m2 s2
>>             case ma of
>>               Left e  -> throwError e
>>               Right a -> do lift $ put (s1,s2')
>>                             return a
>
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Do we have idiom for lifting a state monad into pair of states?

Roman Cheplyaka-2
monad-classes can do this, and more: http://bit.ly/1xBZr3I

On 26/03/15 17:32, lennart spitzner wrote:

> Let me grab this opportunity to advertise the multistate package [1].
>
> The underlying assumption is that the types of the states in your
> stack are distinct. In that case, type inference can give you
> something like "automatic zooming" for a MultiState that contains
> arbitrary heterogenous lists (tuples).
> Generous usage of the Monad(Multi)State type class would thereby
> eliminate the need for do1st and do2nd. See the example in the package.
>
> The package does not (yet!) work well with existing transformers, for
> example one might think of running a StateT on one of the states in a
> MultiStateT. This is not a problem when using MultiStateT exclusively,
> but of course bad for interoperability. I am open for specific
> requests in that direction.
>
> In the last few days I have been working on adding a MultiRWST, but
> this is not completely finished yet (and I am not sure yet how to make
> the interface consistent; the whole run/eval/exec distinction seems
> unintuitive, especially when you have multiple states..)
>
> Lennart
>
>
> [1] https://hackage.haskell.org/package/multistate
>
>
> On 26/03/15 09:28, Ki Yung Ahn wrote:
>> Consider you have developed library routines that act on (State s1 a).
>> For some reason, you need more than one state simultaneously. Let's
>> say two side by side for simple example, that is (State (s1,s2) a). To
>> use library functions on one state monad in a two state monad, we need
>> to wrapper that lifts actions of (State s1 a) to (State (s1,s2) a).
>>
>> It is not difficult to write a lifter for such purposes as below. It
>> is kind of like doing liftA in Applicative libarary, but instead of
>> the last argument 'a' but on the fist argument 's' of (State s a).
>> This seems like an idiom that can often come up. So, I tried some
>> searching in some applicative related libraries and monad transformer
>> related libraries but haven't found this idiom yet.
>>
>> If you had a need for idioms like below, what do you call it? Or, is
>> there a way more general way I've missed that makes this a very
>> special case of it.
>>
>>> import Control.Monad.State
>>> import Control.Monad.Error
>>> import Control.Applicative
>>>
>>> -- lift an action over a state into a pair of states
>>> --
>>> do1st :: State s1 a -> State (s1,s2) a
>>> do1st m1 = do (s1, s2) <- get
>>>               let (a, s1') = runState m1 s1
>>>               put (s1',s2)
>>>               return a
>>>
>>> do2nd :: State s2 a -> State (s1,s2) a
>>> do2nd m2 = do (s1, s2) <- get
>>>               let (a, s2') = runState m2 s2
>>>               put (s1,s2')
>>>               return a
>>>
>>>
>>> -- lift an action over a state with error
>>> -- into a pair of states with error
>>> --
>>> do1 :: Error e => ErrorT e (State s1) a -> ErrorT e (State (s1,s2)) a
>>> do1 m1 = do (s1, s2) <- lift get
>>>             let (ma,s1') = (runState . runErrorT) m1 s1
>>>             case ma of
>>>               Left e  -> throwError e
>>>               Right a -> do lift $ put (s1',s2)
>>>                             return a
>>>
>>>
>>> do2 :: Error e => ErrorT e (State s2) a -> ErrorT e (State (s1,s2)) a
>>> do2 m2 = do (s1, s2) <- lift get
>>>             let (ma,s2') = (runState . runErrorT) m2 s2
>>>             case ma of
>>>               Left e  -> throwError e
>>>               Right a -> do lift $ put (s1,s2')
>>>                             return a
>>
>> _______________________________________________
>> Haskell-Cafe mailing list
>> [hidden email]
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>>
>
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe