A software engineer website

Polysemy: Async gotchas

Gautier DI FOLCO March 08, 2023 [Haskell] #haskell #polysemy #design #effects systems

Polysemy comes with many functions and interpreters relying on -threaded.

However, whenever an issue (such as an Error) happens:

failing :: Members '[Error (), Embed IO] r => Sem r Int
failing = do
  embed $ putStrLn "Failing"
  throw ()

actFailing :: Members '[Error (), Embed IO, Async] r => Sem r ()
actFailing = do
  a <- async failing
  embed $ threadDelay 250
  embed $ putStrLn "Do stuff"
  r <- await a
  embed $ putStrLn "Do even more stuff"
  embed $ print r

main :: IO ()
main = do
  runM (runError @() $ asyncToIO actFailing) >>= print

The main thread stops:

Failing
Left ()
Do stuff

Be reassured, the nominal case works:

working :: Members '[Error (), Embed IO] r => Sem r Int
working = do
  embed $ putStrLn "Working"
  return 42

actWorking :: Members '[Error (), Embed IO, Async] r => Sem r ()
actWorking = do
  a <- async working
  embed $ threadDelay 250
  embed $ putStrLn "Do stuff"
  r <- await a
  embed $ putStrLn "Do even more stuff"
  embed $ print r

main :: IO ()
main = do
  runM (runError @() $ asyncToIO actWorking) >>= print
Working
Do stuff
Do even more stuff
Just 42
Right ()

See the full the code here.