Ошибка типа с использованием транзакционной памяти

Я использую переменные транзакции в haskell, которые я создаю в функции и собираю в список, и которые я даю другой функции для записи значений в:

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"

и я использую эти общие переменные (хранящиеся в ghosts') в функции moveGhost:

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

В то время как я использую ту же стратегию для обоих разделяемых баффов, что и res, я получаю ошибку для 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'

Кто-нибудь знает, в чем проблема с этим TVar и почему это не проблема для любителей TVar?

1 ответ

Решение

Отметив, что это значения в списке, я ожидаю, что [TVar (Maybe Ghost)'] правильный тип, то есть список TVars - и что у вас есть [STM (TVar (Maybe a0))'] вместо этого, потому что вы создаете список STM действия, которые могли бы создать TVarс, но на самом деле не использовать это внутри транзакции.

Итак, где бы у вас ни был этот список TVar-создавая действия, вы захотите сделать что-то вроде sequence превратить это в STM [(TVar (Maybe a0))']одно действие, которое создает список TVars, затем либо связать это внутри транзакции (то есть, используя <- вместо let) или использовать atomically а также для создания TVarв IO, В любом случае, результатом привязки этого значения будет список TVarс, что вы, вероятно, хотите.

Другие вопросы по тегам