Q:

Sharing a mvar between threads

I'm trying to make a program that print arrows until the user press enter (see code bellow). 
The problem is that when I press enter, I see the "stop" string in the console, but it doesn't change the value of m in the outputArrows function.
How can I share the state?
import Control.Concurrent
import Control.Concurrent.Async
import Control.Monad

waitForInput m = do
    getLine
    putStrLn "stop"
    putMVar m True

outputArrows m = do
    stop <- readMVar m
    unless stop $ do
        threadDelay 1000000
        putStr ">"
        outputArrows m

main = do
    m <- newMVar False
    th1 <- async (waitForInput m)
    th2 <- async (outputArrows m)
    wait th1
    wait th2

A:

Your putMVar doesn't actually put a new value in the MVar but blocks indefinitely. MVars are like boxes that can hold only a single value. If you want to replace the value, you need to take out the old value first.
If you don't need the blocking behavior of MVar, you should just use a regular IORef or possibly a TVar if you need to ensure that more complex operations run atomically.

A:

You should use swapMVar instead of putMVar.  As mentioned by @shang, putMVar blocks until the MVar is empty, so the putMVar never finishes:
waitForInput m = do
    getLine
    putStrLn "stop"
    swapMVar m True

Alternatively, you could just use an empty MVar () as a boolean flag:
waitForInput :: MVar () -> IO ()
waitForInput m = do
    getLine
    putStrLn "stop"
    putMVar m ()

outputArrows :: MVar () -> IO ()
outputArrows m = do
    running <- isEmptyMVar m
    when running $ do
        threadDelay 1000000
        putStr ">"
        outputArrows m

main :: IO ()
main = do
    hSetBuffering stdout NoBuffering
    m <- newEmptyMVar
    th1 <- async (waitForInput m)
    th2 <- async (outputArrows m)
    wait th1
    wait th2

