You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There's an outstanding question whether Process r can be an instance of MonadUnliftIO, i.e., have an implementation of withRunInIO :: ((forall a. m a -> IO a) -> IO b) -> m b. There's one for ReaderT (((forall a. ReaderT r m a -> IO a) -> IO b) -> ReaderT r m b), but of course, a Process r uses its inner ReaderT context to track mutable state.
An implementation like the ReaderT one is likely a bad idea, since a call to unliftio's forkIO would then result in 2 (Haskell) threads each with the same ProcessId, and access to their inner CQueue. First and foremost, reading from a CQueue is not necessarily thread-safe. Furthermore, if two threads would send some message to another Process including their (shared) ProcessId, then both go into a receive looking for some response, the response could be delivered to the "wrong" thread.
Instead, we could imagine implementing withRunInIO such that a call to it allocates a new ProcessId (and new process context as a whole, actually). This may work around the issue with forkIO, but brings other issues: e.g., we don't want to run withFile :: MonadUnliftIO m => FilePath -> IOMode -> (Handle -> m a) -> m a in a "new-but-not-really" Process.
To conclude, I don't think there's a way to provide a lawful instance for MonadUnliftIO, but happy to discuss more.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
(This is based on #42)
There's an outstanding question whether
Process r
can be an instance ofMonadUnliftIO
, i.e., have an implementation ofwithRunInIO :: ((forall a. m a -> IO a) -> IO b) -> m b
. There's one forReaderT
(((forall a. ReaderT r m a -> IO a) -> IO b) -> ReaderT r m b
), but of course, aProcess r
uses its innerReaderT
context to track mutable state.An implementation like the
ReaderT
one is likely a bad idea, since a call tounliftio
'sforkIO
would then result in 2 (Haskell) threads each with the sameProcessId
, and access to their innerCQueue
. First and foremost, reading from aCQueue
is not necessarily thread-safe. Furthermore, if two threads would send some message to anotherProcess
including their (shared)ProcessId
, then both go into areceive
looking for some response, the response could be delivered to the "wrong" thread.Instead, we could imagine implementing
withRunInIO
such that a call to it allocates a newProcessId
(and new process context as a whole, actually). This may work around the issue withforkIO
, but brings other issues: e.g., we don't want to runwithFile :: MonadUnliftIO m => FilePath -> IOMode -> (Handle -> m a) -> m a
in a "new-but-not-really"Process
.To conclude, I don't think there's a way to provide a lawful instance for
MonadUnliftIO
, but happy to discuss more.Beta Was this translation helpful? Give feedback.
All reactions