Andrew Coppin wrote:
 run_or s0 x y =
   let
     either_rset1 = sequence $ run s0 x
     either_rset2 = sequence $ run s0 y
either_rset3 = do rset1 <- either_rset1; rset2 <- either_rset2; return (merge rset1 rset2)
 in case either_rset3 of
   Left  e    -> throwError e
   Right rset -> lift rset

Just to expand on that discussion of Control.Monad.ap aka. (Control.Applicative.<*>) in the other half of the thread. The expression

  do rset1 <- either_rset1
     rset2 <- either_rset2
     return (merge rset1 rset2)

follows exactly the pattern Applicative is made for: We execute some actions, and combine their result using a pure function. Which action we execute is independent from the result of the previous actions. That means that we can write this expression as:

  return merge `ap` either_rset1 `ap` either_rset2

Note how we avoid to give names to intermediate results just to use them in the very next line. Since return f `ap` x == f `fmap` x, we can write shorter

  merge `fmap` either_rset1 `ap` either_rset2

Or in Applicative style:

  merge <$> either_rset1 <*> either_rset2

Now that the expression is somewhat shorter, we can inline the either_rset1, 2 and 3 as follows:

  case merge <$> sequence (run s0 x) <*> sequence (run s0 y) of
    Left  e    -> throwError e
    Right rset -> lift rset

Note how the structure of the code reflects what happens. The structure is merge <$> ... <*> ..., and the meaning is: merge is called on two arguments, which are created by running some actions, and the result is again an action.

While we are one it, we can get rid of the pattern matching by employing the either function as follows:

either throwError lift (merge <$> sequence (run s0 x) <*> sequence (run s0 y))

Do you realise, this single snippet of code utilises the ErrorT monad [transformer], the ResultSet monad, *and* the Either monad, all in the space of a few lines?? That's three monads in one function! o_O

Now it fits on a single line!

  Tillmann

_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to