haskelltvar

Type error with the use of transactional memory


I am using Transaction variables in haskell that I instantiate in a function and collect in a list and that I give to another function to write values in:

step player ghosts info = do let unblocked = allPaths (source info) (target info) (graph info)
                         buff <- atomically $ newTVar [[]]
                         atomically $ put buff unblocked
                         let create  = do return newGhostVal
                         let ghosts' = zip (map (\g -> newGhostVal) ghosts) ghosts

                         mapM_ (\g -> forkIO(atomically $ moveGhost buff (fst g) (graph info) (snd g))) ghosts'
                         putStrLn "launched"

and I use these shared variables (stored in ghosts') in the function moveGhost:

moveGhost buff res graph ghost =
             do notBlocked <- get buff
             ...
             writeTVar buff notBlocked'
             writeTVar res (Just ghost'')
             return()

While I use the same strategy for both shared variables buff as res, I get an error for the use of Tvar res:

 Couldn't match expected type `TVar (Maybe Ghost)'
            with actual type `STM (TVar (Maybe a0))'
Expected type: [(TVar (Maybe Ghost), Ghost)]
  Actual type: [(STM (TVar (Maybe a0)), b0)]
In the second argument of `mapM_', namely ghosts'
In a stmt of a 'do' block:
  mapM_
    (\ g
       -> forkIO
            (atomically $ moveGhost buff (fst g) (graph info) (snd g)))
    ghosts'

Does anybody know what the problem is with this TVar and why it isn't a problem for TVar buff?


Solution

  • Noting that these are values in a list, I would expect that [TVar (Maybe Ghost)'] is the correct type--that is, a list of TVars--and that you have [STM (TVar (Maybe a0))'] instead because you're creating a list of STM actions that would create TVars, but not actually using that inside a transaction.

    So, wherever you have that list of TVar-creating actions, you'll want to do something like sequence to turn that into STM [(TVar (Maybe a0))'], a single action that creates a list of TVars, then either bind that inside a transaction (i.e., using <- instead of let) or use atomically as well to create the TVars in IO. Either way, the result of binding that value will be the list of TVars that you probably want.