# [Haskell-cafe] mdo with multiple values

Joachim Breitner mail at joachim-breitner.de
Wed Jan 15 09:57:57 UTC 2014

```Dear List,

a little puzzle.

Given a monad M with a MonadFix instance, and these two functions:
act1 :: T -> M ()
act2 :: a -> M T

I morally want to write this function:
foo :: [a] -> M ()
foo = mdo
mapM_ act1 xs
xs <- mapM act2
return ()

Unfortunately, that will not work: mapM_ will force xs before any of it
can be generated. But morally it should be possible, as the lists passed
to mapM_ and mapM have the same, already known list.

So here is my solution (which is a bit more general, because I happen to
need some that in one place):

mapFstMapSnd :: MonadFix m => [(a -> m (), m a)] -> m ()
mapFstMapSnd xs = const () `liftM` go xs (return [])
where
go [] cont = cont
go ((f,s):xs) cont = mdo
f v
(v:vs) <- go xs \$ do
vs <- cont
v <- s
return (v:vs)
return vs

Using that, I can write
foo = mapFstSnd . map (x -> (act1, act2 x))

Are there better solutions? Simpler ones? Or possibly ones that do not
require a partial pattern?

Hmm, and thinking while writing lets me come up with

data FunSplit m where
FunSplit :: forall m a . (a -> m ()) -> m a -> FunSplit m

mapFstMapSnd :: forall m. MonadFix m => [FunSplit m] -> m ()
mapFstMapSnd xs = const () `liftM` go xs (return ())
where
go :: [FunSplit m] -> m b -> m b
go [] cont = cont
go (FunSplit f s:xs) cont = mdo
f v
(v,vs) <- go xs \$ do
vs <- cont
v <- s
return (v,vs)
return vs

foo :: [SPut] -> SPut
foo = mapFstMapSnd . map go
where go x = FunSplit act1 (act2 x)

Any suggestions for improvement?

Thanks,
Joachim

--
Joachim Breitner
e-Mail: mail at joachim-breitner.de
Homepage: http://www.joachim-breitner.de
Jabber-ID: nomeata at joachim-breitner.de

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: This is a digitally signed message part
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20140115/bebe2979/attachment.sig>
```

More information about the Haskell-Cafe mailing list