Opencv 再论Haskell中的破环

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

我有一小段代码,它在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
  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)
,因此它返回a
zmqz(或()b)
,而我期望的是a
zmqz()
@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 ()))