<div dir="ltr">One solution is to use lens package.<div><br></div><div>The lens package provides an interesting combinator, zoom, in Control.Lens.Zoom[1]:</div><div><br></div><div><pre style="font-size:13px;margin-top:0.8em;margin-bottom:0.8em;padding:0.25em;line-height:16.1200008392334px;overflow:auto;border-bottom-width:0.25em;border-bottom-style:solid;border-bottom-color:white;color:rgb(0,0,0);background:rgb(229,237,244)"><code style="margin:0px;padding:0px"><a href="https://hackage.haskell.org/package/lens-4.8/docs/Control-Lens-Zoom.html#v:zoom" style="color:rgb(171,105,84);margin:0px;padding:0px;text-decoration:none">zoom</a></code> :: <code style="margin:0px;padding:0px"><a href="https://hackage.haskell.org/package/base-4.7.0.2/docs/Control-Monad.html#t:Monad" style="color:rgb(171,105,84);margin:0px;padding:0px;text-decoration:none">Monad</a></code> m             => <code style="margin:0px;padding:0px"><a href="https://hackage.haskell.org/package/lens-4.8/docs/Control-Lens-Type.html#t:Lens-39-" style="color:rgb(171,105,84);margin:0px;padding:0px;text-decoration:none">Lens'</a></code> s t      -> <code style="margin:0px;padding:0px"><a href="https://hackage.haskell.org/package/mtl-2.1.3.1/docs/Control-Monad-State-Strict.html#v:StateT" style="color:rgb(171,105,84);margin:0px;padding:0px;text-decoration:none">StateT</a></code> t m a -> <code style="margin:0px;padding:0px"><a href="https://hackage.haskell.org/package/mtl-2.1.3.1/docs/Control-Monad-State-Strict.html#v:StateT" style="color:rgb(171,105,84);margin:0px;padding:0px;text-decoration:none">StateT</a></code> s m a</pre></div><div><br></div><div>Lens' s a is the type of accessors to `a`. When it comes to tuples, you can use</div><div><br></div><div>_1 :: Lens' (a, b) a</div><div>_2 :: Lens' (a, b) b</div><div><br></div><div>So do1st, do2nd are zoom _1, zoom _2 respectively.</div><div><br></div><div>zoom also can be used for monad transformer stacks; zoom _1 may have the type of do1.</div><div><br></div><div>[1] <a href="https://hackage.haskell.org/package/lens-4.8/docs/Control-Lens-Zoom.html">https://hackage.haskell.org/package/lens-4.8/docs/Control-Lens-Zoom.html</a></div></div><div class="gmail_extra"><br><div class="gmail_quote">2015-03-26 17:28 GMT+09:00 Ki Yung Ahn <span dir="ltr"><<a href="mailto:kyagrd@gmail.com" target="_blank">kyagrd@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Consider you have developed library routines that act on (State s1 a).<br>
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).<br>
<br>
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.<br>
<br>
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.<br>
<br>
> import Control.Monad.State<br>
> import Control.Monad.Error<br>
> import Control.Applicative<br>
><br>
> -- lift an action over a state into a pair of states<br>
> --<br>
> do1st :: State s1 a -> State (s1,s2) a<br>
> do1st m1 = do (s1, s2) <- get<br>
>               let (a, s1') = runState m1 s1<br>
>               put (s1',s2)<br>
>               return a<br>
><br>
> do2nd :: State s2 a -> State (s1,s2) a<br>
> do2nd m2 = do (s1, s2) <- get<br>
>               let (a, s2') = runState m2 s2<br>
>               put (s1,s2')<br>
>               return a<br>
><br>
><br>
> -- lift an action over a state with error<br>
> -- into a pair of states with error<br>
> --<br>
> do1 :: Error e => ErrorT e (State s1) a -> ErrorT e (State (s1,s2)) a<br>
> do1 m1 = do (s1, s2) <- lift get<br>
>             let (ma,s1') = (runState . runErrorT) m1 s1<br>
>             case ma of<br>
>               Left e  -> throwError e<br>
>               Right a -> do lift $ put (s1',s2)<br>
>                             return a<br>
><br>
><br>
> do2 :: Error e => ErrorT e (State s2) a -> ErrorT e (State (s1,s2)) a<br>
> do2 m2 = do (s1, s2) <- lift get<br>
>             let (ma,s2') = (runState . runErrorT) m2 s2<br>
>             case ma of<br>
>               Left e  -> throwError e<br>
>               Right a -> do lift $ put (s1,s2')<br>
>                             return a<br>
<br>
______________________________<u></u>_________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org" target="_blank">Haskell-Cafe@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" target="_blank">http://mail.haskell.org/cgi-<u></u>bin/mailman/listinfo/haskell-<u></u>cafe</a><br>
</blockquote></div><br></div>