Opencv 再论Haskell中的破环
我有一小段代码,它在zeromq Pull套接字上接收帧并在opencv窗口中显示:Opencv 再论Haskell中的破环,opencv,haskell,zeromq,Opencv,Haskell,Zeromq,我有一小段代码,它在zeromq Pull套接字上接收帧并在opencv窗口中显示: 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
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!
但是当然
quit
将参数包装在左边,此解决方案不会编译。读取并写入IORef
,然后使用
main=runZMQ$do
receiver让回调返回一个one()()
,然后在传递给forever之前将其包装在ExceptT
中,怎么样?差不多
runExceptT . forever . ExceptT $ 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
if (key == 27)
then (return (Left ()))
else (return (Right ()))
runExceptT。永远。除了$do
缓冲区do
CV.imshow窗口img
我没有考虑IORef,好点。但是,当我尝试它时,我必须在liftIO
whileM_uu时,我最终会遇到ZMQ z()
和IO()
之间相同的冲突,当我使用receive
时。现在我尝试第二种解决方案……好的,关于第二种解决方案loop
具有签名loop::ZMQ z()
但是CV.withWindow::String->(Window->IO a)->IO a
因此,如果我在CV.withWindow
之前执行liftIO
,我仍然运气不佳。我怀疑后一种解决方案是否会在每个循环中泄漏内存。我猜withWindow
应该是一种尾部递归,但我不知道OpenCV是如何工作的(而且我找不到它,即使是在堆栈上)@mezzomondo我误解了runZMQ
的类型,很抱歉。我已经更新了whileM\ucode>/IORef
解决方案的新方案,但我没有安装zeromq来测试它;无论如何,试试看。谢谢你@daniel wagner,括号中的liftIO
是缺失的一位。现在它工作了。CV.withWindow
的类型是什么?(通常:模块OpenCV
来自哪里?OpenCV
来自并根据CV.withWindow::String->(Window->IO a)->IO a
好,因为withWindow
返回您传递的操作的结果,还有另一种方法。我已经扩展了我的答案,尝试一下<代码>运行异常。永远。除了:Monad m=>m(或ea)->m(或eb)
,因此它返回azmqz(或()b)
,而我期望的是azmqz()
@mezzomondo您可以在do块中的zmqz(或()b)
之后放置return()
,您可以使用函数void::Functor f=>fa->
从Control.Monad
删除返回值。
main = runZMQ $ do
receiver <- socket Pull
bind receiver "tcp://*:5554"
continue <- liftIO $ newIORef True
whileM_ (liftIO $ readIORef continue) $ 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) $ writeIORef continue False
main = runZMQ $ do
receiver <- socket Pull
bind receiver "tcp://*:5554"
let loop = do
buffer <- receive receiver
let img = CV.imdecode CV.ImreadUnchanged buffer -- simple decoder
key <- liftIO . CV.withWindow "Video" $ \window -> do
CV.imshow window img
CV.waitKey 10
when (key /= 27) loop
loop
runExceptT . forever . ExceptT $ 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
if (key == 27)
then (return (Left ()))
else (return (Right ()))