简体   繁体   中英

return TVar after initialisation

Is it possible to return the newly created TVar in a do block? I tried to implement this using this code:

type Buffer a = TVar [[(a,a)]]

newBuffer :: STM (Buffer a)
newBuffer = newTVar [[]]

launchGhosts :: [[(String,String)]] -> Buffer String
launchGhosts unblocked = do buff <- atomically newBuffer
                            atomically $ put buff unblocked
                            return buff


computeBlock :: Buffer String -> IO()
computeBlock buff = do i <- atomically $ get buff
                       putStrLn $ show i

put :: Buffer a -> [[(a,a)]] -> STM ()
put buff x = do writeTVar buff x

get :: Buffer a -> STM [[(a,a)]]
get buff = do x <- readTVar buff
              return x

And this should allow me to initialize the shared memory and use it at another place in the program. The main reason that I want to separate the memory initialization is to call the concurrent functions multiple times, without initialising the memory again and again.

The type checker trows these two errors:

pacman.hs:65:29:
No instance for (Monad TVar)
  arising from a do statement
Possible fix: add an instance declaration for (Monad TVar)
In a stmt of a 'do' block: buff <- atomically newBuffer
In the expression:
  do { buff <- atomically newBuffer;
       atomically $ put buff unblocked;
       computeBlock buff;
       return buff }
In an equation for `launchGhosts':
    launchGhosts unblocked
      = do { buff <- atomically newBuffer;
             atomically $ put buff unblocked;
             computeBlock buff;
             .... }

pacman.hs:65:37:
    Couldn't match expected type `TVar t0' with actual type `IO a0'
    In the return type of a call of `atomically'
    In a stmt of a 'do' block: buff <- atomically newBuffer
    In the expression:
      do { buff <- atomically newBuffer;
           atomically $ put buff unblocked;
           computeBlock buff;
           return buff }

Does anybody know what the problem is, or maybe another way to implement the idea behind this code?

update:

launchGhosts :: [[(String,String)]] -> IO(Buffer String)
launchGhosts unblocked = do buff <- atomically newBuffer
                            atomically $ put buff unblocked
                            return buff


computeBlock :: IO(Buffer String) -> IO()
computeBlock buff = do i <- atomically $ get buff
                       putStrLn $ show i

update:

pacman.hs:71:46:
Couldn't match expected type `Buffer a0'
            with actual type `IO (Buffer String)'
In the first argument of `get', namely `buff'
In the second argument of `($)', namely `get buff'
In a stmt of a 'do' block: i <- atomically $ get buff

The solution is to declare launchGhosts as

launchGhosts :: [[(String,String)]] -> IO (Buffer String)

The problem is that you declared launchGhosts as returning a Buffer String , which is a TVar [[(String, String)]] . Since launchGhosts uses a do block, that requires a Monad instance for its result type, which according to your signature is TVar . This is what the first error is about.

The other problem is that atomically has the type STM a -> IO a , so atomically newBuffer is an IO something (the actual type). But you're using it in a do block that was declared to have a Buffer (ie TVar ) type, so it should have that type as well (the expected type). This is what the second error is about.

Edit:

Why did you change the type signature of computeBlock ? I never said anything about computeBlock .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM