[Haskell-cafe] Auto elimination of MVars using a monad or monad transformer.

Chris Dew cmsdew at gmail.com
Fri Feb 25 07:41:35 CET 2011

Hello, just like everyone else, I have a question about monads.  I've
read the tutorials, written one monad myself (not in this email), but
I still consider myself a Haskell beginner.

* Does GHC eliminate unneeded MVars during compilation?

I'm expecting that it doesn't, as that would mean optimising away
ForkIOs, which would be quite a thing to do.  I've included example
code below.

* Is there a monad which allows their automatic elimination of MVars
(or their creation only when necessary)?

This would be similar to how the IO monad allows you to do purely
functional things with a do block, using let.

I've had a go at a lifting function, which wraps a pure function into
an IO action which forever reads from one MVar and writes to another.
What I'm looking for is some form of Monadic context in which many
pure functions, MVar fillers and MVar consumers could be linked
together, where only the necessary MVars remain (or were created) at
compilation time.

* Would this be a monad, or a monad transformer?

* Can you specialise a monad transformer on a single base (in this
case IO) so that you can use forkIO in the bind or return?



module Main (

import Control.Concurrent (forkIO, MVar, newEmptyMVar, putMVar,
takeMVar, ThreadId, threadDelay)
import Control.Monad (forever)

stepA :: MVar String -> IO ()
stepA boxa = forever $ do
                      line <- getLine
                      putMVar boxa line

stepB :: MVar String -> IO ()
stepB boxb = forever $ do
                      line <- takeMVar boxb
                      putStrLn line

-- This simply wraps a string in brackets.
bracket :: String -> String
bracket x = "(" ++ x ++ ")"

-- This lifts a function into an action which forever performs the function
-- between the two MVars given.
lft :: (a -> b) -> MVar a -> MVar b -> IO ()
lft f c d = forever $ do
                     x <- takeMVar c
                     putMVar d (f x)

-- Just like C's main.
main :: IO ()
main = do
      box <- newEmptyMVar
      box2 <- newEmptyMVar
      forkIO $ stepA box
      forkIO $ lft bracket box box2
      forkIO $ stepB box2
      threadDelay 10000000 -- Sleep for at least 10 seconds before exiting.

More information about the Haskell-Cafe mailing list