[Haskell-cafe] Do we have idiom for lifting a state monad into pair of states?

Fumiaki Kinoshita fumiexcel at gmail.com
Thu Mar 26 08:44:28 UTC 2015


One solution is to use lens package.

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

zoom <https://hackage.haskell.org/package/lens-4.8/docs/Control-Lens-Zoom.html#v:zoom>
:: Monad <https://hackage.haskell.org/package/base-4.7.0.2/docs/Control-Monad.html#t:Monad>
m             => Lens'
<https://hackage.haskell.org/package/lens-4.8/docs/Control-Lens-Type.html#t:Lens-39->
s t      -> StateT
<https://hackage.haskell.org/package/mtl-2.1.3.1/docs/Control-Monad-State-Strict.html#v:StateT>
t m a -> StateT
<https://hackage.haskell.org/package/mtl-2.1.3.1/docs/Control-Monad-State-Strict.html#v: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.

[1] https://hackage.haskell.org/package/lens-4.8/docs/Control-Lens-Zoom.html

2015-03-26 17:28 GMT+09:00 Ki Yung Ahn <kyagrd at gmail.com>:

> 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
> Haskell-Cafe at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20150326/02c55029/attachment.html>


More information about the Haskell-Cafe mailing list