Coroutine with StateT and ST and IO
having some trouble with a group of monads I'm trying to combine.
I'm using monad-coroutine, State and lens (as I have deeply nested state).
I had an initial approach where there was a working solution. The main point here is that I can request to execute IO
tasks outside of Coroutine.
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
module Main where
import Control.Monad.Coroutine (Coroutine(..), suspend, resume)
import Control.Monad.State (State, MonadState, MonadIO)
import Control.Monad.State (lift, get, put, liftIO, runState)
import System.Environment (getArgs)
type MyType = Coroutine IORequest (State MyState)
instance (MonadState s m) => MonadState s (Coroutine IORequest m) where
get = lift get
put = lift . put
io :: MonadIO m => IO a -> m a
io = liftIO
data IORequest x = forall a. RunIO (IO a) (a -> x)
instance Functor IORequest where
fmap f (RunIO x g) = RunIO x (f . g)
data MyState = MyState { _someInt :: Int }
initialState :: MyState
initialState = MyState 1
request :: Monad m => IO a -> Coroutine IORequest m a
request x = suspend (RunIO x return)
myLogic :: MyType [String]
myLogic = do
args <- request (io getArgs)
request (io (print args))
-- do a lot of useful stuff here
return args
runMyType :: MyType [String] -> MyState -> IO ()
runMyType logic state = do
let (req, state') = runState (resume logic) state
case req of
Left (RunIO cmd q') -> do
result <- cmd
runMyType (q' result) state'
Right _ -> return ()
main :: IO ()
main = runMyType myLogic initialState
Now, at some point a simple State became not enough and I am in a need of ST. I started to try to get the ST
inside StateT
but for some reason cannot come up with an idea how to properly handle IO
outside of coroutine. Is there any way to come up with similar runMyType
when there is a change in the Coroutine
?
type MyType s = Coroutine IORequest (StateT (MyState s) (ST s))
initialState :: ST s (MyState s)
initialState = do
a <- newSTRef 0
return (MyState a)
Whatever I try to come up with throws some error about s
escaping or Couldn't match type 's' with 's2'
and so on... Maybe some other order of monad stacking will help? Or is it at all possible?
And another question if you have some time: what is the difference between the above MyType s
and this one:
type MyType = forall s. Coroutine IORequest (StateT (MyState s) (ST s))
链接地址: http://www.djcxy.com/p/53214.html
上一篇: 有没有办法手动打开asyncio事件循环
下一篇: 具有StateT和ST和IO的协程