Search code examples
haskellstm

Software Transaction Memory in Haskell: Couldn't match expected type STM a0 with actual type IO ()


I have a small program that defines an account, a withdraw function and attempts to withdraw from it. However, it doesn't compile due and throws the following error:

Couldn't match expected type ‘(STM a0 -> IO a0)
                                    -> STM () -> IO ()’
                  with actual type ‘IO ()’

It seems like the compiler doesn't recognise the conversion from STM to IO. Any pointers would be great.

import System.IO
import Control.Concurrent.STM

type Account = TVar Int

withdraw :: Account -> Int -> STM ()
withdraw acc amount = do
    bal <- readTVar acc    
    writeTVar acc (bal - amount)

good :: Account -> IO ()
good acc = do
    hPutStr stdout "Withdrawing..."
    {-hi-}atomically{-/hi-} (withdraw acc 10)

main = do
    acc <- atomically (newTVar 200)
    good acc 
    hPutStr stdout "\nDone!\n"

Solution

  • The {-hi-} and {-/hi-} comment result in "indenting" the automically, so as a result, you wrote hPutStr stdout "Withdrawing..." atomically (withdraw acc 10). For example if you write:

    good :: Account -> IO ()
    good acc = do
            hPutStr stdout "Withdrawing..."
     {-hi-} atomically (withdraw acc 10)

    it works fine, since the "noise" (the {-hi-} comment) does not result in inlining the atomically function.

    The comment indeed has no effect semantically, but you can consider it replaced by whitespace.