4

Again on breaking loops at Haskell

 3 years ago
source link: https://www.codesd.com/item/again-on-breaking-loops-at-haskell.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Again on breaking loops at Haskell

advertisements

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.


Read and write an IORef, and use whileM_.

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

Or have your loop call itself explicitly as appropriate:

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




Recommend

  • 145

    31 October 2017JavaScript loops - how to handle async/await

  • 81
    • ashishchaudhary.in 7 years ago
    • Cache

    Implementing C-Style For-Loops In Kotlin

    Kotlin does not have C-style for-loops. This is fine because I prefer using the idiomatic for-loops (built to use iterators) anyway. But there is a big problem: Kotlin does not allow dynamic limiting conditions in its for-loops (See this thread)...

  • 24
    • www.tuicool.com 6 years ago
    • Cache

    Feedback Loops

    How do we get better faster? It’s amazing to consider the amount of money, thought and effort that has gone into solving that one simple problem in software development over the past 2 decades. Here’s a sma...

  • 34
    • www.tuicool.com 6 years ago
    • Cache

    Perl foreach loops

    A foreach loop runs a block of code for each element of a list. No big whoop,...

  • 39

    Today, we're going to discuss control structures and loops in PHP. I'll show you how to use all the main control structures that are supported in PHP, like if, else, for, foreach, while and more. What Is a Contr...

  • 31
    • www.tuicool.com 6 years ago
    • Cache

    Begin and End with range-based for loops

    On slack the other day, someone mentioned that lots of companies don't use range-based for loops in their code because they use PascalCase identifiers, and their containers thus have

  • 4
    • Github github.com 3 years ago
    • Cache

    GitHub - fumieval/Haskell-breaking-changes

    This document describes a list of upcoming/proposed changes to Haskell core/de facto libraries. Ongoing: the change is already rolled out. Upcoming: the change is made upstream, and will...

  • 7
    • www.wired.com 2 years ago
    • Cache

    The Breaking Point Is Here—Again

    The Breaking Point Is Here—AgainTragedies converge, apocalypse colors the air, and digital realities no longer suffice. Eventually everything, and everyone, cracks.

  • 6

    [repost] man's breaking the rules again, I can't even imagine [repost] man's breaking the rules again, I can't even imagine

  • 4
    • blog.josemcastaneda.com 1 year ago
    • Cache

    Breaking things again

    Breaking things again Yeah, I do that quite a bit. The site was down for a bit on and off the last couple of days because of a fatal error. It was the Gutenberg plugin having some hiccups. It was fine since it wa...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK