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

Ki Yung Ahn kyagrd at gmail.com
Thu Mar 26 08:56:09 UTC 2015


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
>> Haskell-Cafe at haskell.org
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
>>




More information about the Haskell-Cafe mailing list