Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 5941355
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 22, 20262026-05-22T16:05:53+00:00 2026-05-22T16:05:53+00:00

I’ve got the following code in an old project of mine: — |ImageOperation is

  • 0

I’ve got the following code in an old project of mine:

-- |ImageOperation is a name for unary operators that mutate images inplace.
newtype ImageOperation c d = ImgOp (Image c d-> IO ())

-- |Compose two image operations
(#>) :: ImageOperation c d-> ImageOperation c d -> ImageOperation c d
(#>) (ImgOp a) (ImgOp b) = ImgOp (\img -> (a img >> b img))

-- |An unit operation for compose 
nonOp = ImgOp (\i -> return ())

-- |Apply image operation to a Copy of an image
img <# op = unsafeOperate op img

-- | Apply the operation on a clone of an image
operate (ImgOp op) img = withClone img $ \clone -> 
                                           op clone >> return clone

unsafeOperate op img = unsafePerformIO $ operate op img

Its main purpose is to allow composition of opencv operators that run in place and accept an image of the same format and a dimension. It is an important optimization, since for example, without it drawing 100 lines would allocate the 1mb image hundred times. The current interface works nicely but I have a feeling that there might be a some standard approach to doing thing like this. So,

  1. Am I doing something that appears elsewhere with standardized name?
  2. Can I do this better?
  3. Can this approach be generalized for binary operators in a way that doesn’t allow unsafe references to specific states of the mutable image?

Edit:
An example of a binary operation is ‘take an image, make a blurred copy and subtract from the original. Return the result’. The effective version with minimal copies in just the IO monad would be something like:

poorMansHighPass img = do
    x <- clone img
    gaussian (5,5) x
    subtract x img
    return x

Although I can make an operator like this, I would much prefer something that is more of a composition of primitive operators than ugly bit of unsafe io code.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-22T16:05:54+00:00Added an answer on May 22, 2026 at 4:05 pm

    Well, I can at least point out what to call some of the patterns you’re using currently.

    So we have a type representing a reference to some mutable data, and a type representing opaque operations on it. We also have a null op and a composition function, which gives an obvious Monoid instance:

    instance Monoid (ImageOperation c d) where
        mempty = nonOp
        mappend = (#>)
    

    So that’s at least one standard name you could use.

    Further, the above Monoid is actually a straightforward result of the properties of two other well-known types:

    • The Applicative and/or Monad instance for (->) a describes combining functions by applying all of them to a single argument, as with the image in the composition function. Basically a lightweight, in-line version of the Reader monad.

    • The Monad instance for IO, or rather the monoidal structure it implies. By fixing IO‘s type parameter to (), the monad laws reduce to a simple monoid, with return () as unit and (>>) as the monoid operation.

    To reconstruct your combination, given two functions (unwrapped ImageOperations) and imagining that the implied monoid for IO () is an actual instance, we could write:

    nonOp = pure mempty
    
    x #> y = mappend <$> x <*> y
    

    It’s also worth noting that the combination of something like a reader monad and a monad allowing mutable state essentially describes “a surrounding environment with mutable references”, a.k.a. mutable global variables, except that “global” here means “within a single computation of the combined monad”. I’ve actually constructed such a monad explicitly, using ReaderT and STM.

    That handles combining operations. To actually run an operation, you need an Image and I’m gathering you want to only operate on clones, the creation of which is inefficient. Fortunately, considering how very general the above construction for the Monoid is, there’s really nothing you can’t cram into an ImageOperation before actually running it. Generating the clone is presumably an IO operation and is what I assume is going on in operate–there’s probably not really any other way to do that.

    Beyond that, if you’re interested in alternate ways to structure the whole thing, one obvious variant would be to wrap Image instead into something representing the process of constructing one, with operators merged in to transform the image being produced using something like operate. I don’t know if this would actually gain you anything, though.

    In fact, I’m inclined to doubt that there’re really any other ways to do this. You’re writing an FFI binding to a highly imperative library and there’s only so much you can do to disguise that.

    I’m not sure, however, why you have an unsafe version of operate. What practical purpose would this serve?

    I’m also not sure what kind of binary operators you’d like to generalize this to–there’s not much else you can do operating on ImageOperation besides what you have here. Do you mean generalizing ImageOperation to work on more than one mutable reference to an image? Or something involving operations on images that return something other than just IO ()?


    EDIT: Okay, let’s look at how one might decompose poorMansHighPass. Hopefully I’m correctly reading what it’s doing here:

    First, gaussian is independent and can be factored out as its own operation: gauss' = ImgOp . gaussian.

    Next, subtract can also be factored out, parameterized by an additional Image: subtr' = ImgOp . flip subtract.

    These two are the core of the function, and they can be combined in the usual manner: poorMansHP' img = gauss' (5, 5) #> subtr' img. The last thing needed to recover the original function is that the img argument given to poorMansHP' must be the same image whose clone is passed to the inner function by operate.

    First we’ll explicitly unwrap the ImageOperation and use that in the reimplementation:

    poorMansHighPass img = 
        let (ImgOp op) = gauss' (5, 5) #> subtr' img
        in do x <- clone img
              op x
              return x
    

    Substitute withClone for the use of clone here:

    poorMansHighPass img = 
        let (ImgOp op) = gauss' (5, 5) #> subtr' img
        in withClone img $ \x -> do op x
                                    return x
    

    Desugar the do block:

    poorMansHighPass img = 
        let (ImgOp op) = gauss' (5, 5) #> subtr' img
        in withClone img $ \x -> op x >> return x
    

    …which obviously contains a reimplementation of operate, so replace that and simplify:

    poorMansHighPass img = operate (gauss' (5, 5) #> subtr' img) img
    

    More interesting would be implementing poorMansHighPass in a way that modifies the argument instead of the clone, which would allow it to be packaged up as an ImageOperation itself. Possibly that’s what it’s supposed to be doing, and I misread your code?

    Anyway, the basic structure of the refactoring would be the same, but you’d need a different composition operator–instead of applying two operators to the same input in sequence, it would need to create a clone of the input internally before recombining the results. I have a rough idea what kind of structure would make this work smoothly, which I can elaborate on if you’d like but I’ll have to work through it a bit to make sure it behaves properly.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I've got a string that has curly quotes in it. I'd like to replace
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
I ran into a problem. Wrote the following code snippet: teksti = teksti.Trim() teksti
link Im having trouble converting the html entites into html characters, (&# 8217;) i
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
I have this code to decode numeric html entities to the UTF8 equivalent character.
I have a French site that I want to parse, but am running into
I'm using v2.0 of ClassTextile.php, with the following call: $testimonial_text = $textile->TextileRestricted($_POST['testimonial']); ... and
I am doing a simple coin flipping experiment for class that involves flipping a

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.