I have a small piece of code that receives frames on a zeromq Pull socket and displays it in a opencv window:
module Main where
import Control.Monad
import qualified OpenCV as CV
import System.ZMQ4.Monadic
import System.Exit
main :: IO()
main = runZMQ $ do
receiver <- socket Pull
bind receiver "tcp://*:5554"
-- do some stuff not relevant
forever $ do
buffer <- receive receiver
let img = CV.imdecode CV.ImreadUnchanged buffer -- simple decoder
liftIO $ CV.withWindow "Video" $ \window -> do
CV.imshow window img
key <- CV.waitKey 10
when (key == 27) exitSuccess -- <- UGLY!
What I would like to find is a way to break the loop that allows me more control. I'm aware of the EitherT solution proposed by Gabriel Gonzalez here (that I like very much) but I'm not able to implement it in the CV.withWindow
context, for example:
quit :: (Monad m) => e -> EitherT e m r
quit = left
loop :: (Monad m) => EitherT e m a -> m e
loop = fmap (either id id) . runEitherT . forever
main :: IO()
main = runZMQ $ do
receiver <- socket Pull
bind receiver "tcp://*:5554"
loop $ do
buffer <- receive receiver
let img = CV.imdecode CV.ImreadUnchanged buffer -- simple decoder
liftIO $ CV.withWindow "Video" $ \window -> do
CV.imshow window img
key <- CV.waitKey 10
when (key == 27) $ quit ()
But of course quit
wraps the argument in a Left and this solution doesn't compile.