Изменить и распечатать состояние с помощью STM

Я могу инициализировать состояние с помощью STM и распечатать его:

module Main where

import Control.Concurrent.STM

data State = State {name :: String} deriving (Show)

type MyAppState = TVar [State]

initState :: STM MyAppState
initState = newTVar [State "hi"]

main :: IO ()
main =  
  do 
    state <- atomically initState
    stateToPrint <- readTVarIO state
    putStrLn (show stateToPrint)

Я попытался создать функцию для обновления состояния:

updateState :: String -> State -> State 
updateState newName s = State newName : s

Но я не уверен, как разместить его в основном блоке do без того, чтобы компилятор выдал ошибку, поскольку он ожидает тип State, но ему передается MyAppState.


person timothyylim    schedule 27.08.2019    source источник


Ответы (1)


Вы можете использовать writeTVar :: TVar a -> a -> STM ()< /сильный>:

main :: IO ()
main = do 
    state <- atomically initState
    stateToPrint <- readTVarIO state
    putStrLn (show stateToPrint)
    atomically (readTVar state >>= writeTVar state . fmap (updateState "foo"))

Таким образом, здесь мы читаем содержимое state, затем передаем его через fmap updateState для обновления элементов в списке, а затем записываем это в переменную state.

При этом может быть полезно поискать преобразователь монад состояния, как в Control.Monad.Trans.State модуль из transformers пакет.

Обратите внимание, что ваша функция updateState не определена должным образом, вы, возможно, захотите определить это так:

updateState :: String -> State -> State 
updateState newName (State s) = State (newName ++ s)
person Willem Van Onsem    schedule 27.08.2019
comment
Извините, только еще одна вещь, я думаю, что может быть проблема с тем, как я определил свое состояние. Я получаю сообщение об ошибке: Не удалось сопоставить ожидаемый тип «[Состояние]» с фактическим типом «Состояние». - person timothyylim; 27.08.2019
comment
@timothyylim: ты использовал fmap? Определив свой TVar для хранения списка State, вам нужен способ обработки такого списка. - person Willem Van Onsem; 27.08.2019
comment
Да, я использую fmap, как было предложено! - person timothyylim; 27.08.2019
comment
@timothyylim: ошибка в вашем updateStateFunction. - person Willem Van Onsem; 27.08.2019