ForkIO with a stateT
haskell
Solution
You cannot have a `State` computation running in multiple threads sharing the same state because behind the scenes, the `State` monad is nothing more than a chain of function calls that passes the state value on to the next function in the chain.
For multithreaded code you can replace `StateT s IO` with `ReaderT (IORef s) IO` and use
forkIO $ runReaderT (h event) stateVar
to fork new threads (where `stateVar` is an `IORef` that contains the shared state).
Inside the `ReaderT` stack, you read the current shared state with
stateVar <- ask
s <- lift $ readIORef stateVar
and update it with
stateVar <- ask
lift $ atomicModifyIORef stateVar f
where `f` is a pure function that takes the current state and returns the modified state plus an auxiliary result.
If you need anything more fancy (e.g. modify the state using monadic functions), then you should use either `MVar` or `TVar` instead of `IORef`.
Problem
How can we make a user pass an eventHandler, which uses a stateMonad but is invoked in a separate thread? For example the in the following example, how should the forkIO be called so that eventHandler can invoke operate? I am new to Haskell, please correct me if this is a wrong api to expose to users? ``` data MyTypeResult a = MyTypeValue a data MyTypeState = MyTypeState {_counter :: Int} newtype MyType a = MyType { unMyType :: StateT MyTypeState IO (MyTypeResult a) } instance Monad MyType where (>>=) = myTypeBind return = myTypeReturn fail = myTypeFail myTypeBind = undefined myTypeReturn = undefined myTypeFail = undefined type Event = String type Handler = Event -> MyType () doSomethingAwesome :: MyType Event doSomethingAwesome = undefined operate :: String -> MyType () operate = undefined start :: Handler -> MyType () start h = do event <- doSomethingAwesome --forkIO $ h event -- The line that is troubling return () testHandler :: Event -> MyType() testHandler _ = operate "abcd" myMain = start testHandler ```