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 6852531
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 27, 20262026-05-27T01:22:56+00:00 2026-05-27T01:22:56+00:00

I try to make a simple counter. My counters do not go up however.

  • 0

I try to make a simple counter. My counters do not go up however. It seems to me as if they are re-initialized every time by the function “inc” or maybe the (n+1) does not work. How do I best fix this?

inc :: Int -> IO Int
inc n = return (n+1)

main :: IO ()
main = do
  let c = 0
  let f = 0
  putStrLn "Starting..."
  conn <- connect "192.168.35.62" 8081
  time $
    forM_ [0..10000] $ \i -> do
      p <- ping conn "ping"
      if p=="pong" then inc c
         else inc f
  printf "Roundtrips %d\n" (c::Int)
  • 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-27T01:22:56+00:00Added an answer on May 27, 2026 at 1:22 am

    Though mutable variables can be used in Haskell as shown by other commenters, it is not a good style: mutation should not be used in most cases.

    The inc function accepts its argument by value, that is, it doesn’t modify its argument. Also, the variables declared by let keep their initial values, so you cannot change them.

    How do you write if no variable can ever be changed? The answer is:

    1. instead of modifying something in-place, return a new value
    2. for loops, use recursion

    Fortunately, you rarely need to write recursion yourself, as most of recursive patterns are already in the standard library.

    In your case you need to perform several IO actions and return the final value of the two counters. Let’s start from one action:

    let tryOnePing (c, f) i = do
        p <- ping conn "ping"
        return $ if p == "pong" then (c+1, f) else (c, f+1)
    

    Here we declare a local function with 2 parameters: the current values of the counters, packed in a tuple (Int, Int) (a structure in other languages) and current iteration Int. The function performs IO actions and returns modified values of the counters IO (Int, Int). This all is indicated in its type:

    tryOnePing :: (Int, Int) -> Int -> IO (Int, Int)
    

    ping returns a value of IO String type. To compare it, you need a String without IO. To do that, you should use >>= function:

    let tryOnePing (c, f) i = ping conn "ping" >>= \p -> {process the string somehow}
    

    As this pattern is common, it can be written like this

    let tryOnePing (c, f) i = do
        p <- ping conn "ping"
        {process the string somehow}
    

    But the meaning is exactly the same (compiler translates do notation into applications of >>=).

    The processing shows a few more common patterns:

    if p == "pong" then (c+1, f) else (c, f+1)
    

    Here if is not an imperative if but more like a ternary condition ? value1 : value2 operator in other languages. Also note, that our tryOnePing function accepts (c, f) and returns either (c+1, f) or (c, f+1). We used tuples as we need to work only with 2 counters. In case of big number of counters, we would need to declare a structure type and use named fields.

    The value of the whole If construct is a tuple (Int, Int). ping is an IO action, so tryOnePing must be an IO action too. The return function is not an imperative return but a way to convert (Int, Int) to IO (Int, Int).

    So, as we have tryOnePing, we need to write a loop to run it 1000 times. Your forM_ was not a good choice:

    1. It doesn’t pass our two counters between iterations
    2. _ indicates that it throws the final value of the counters away instead of returning it

    You need here not forM_ but foldM

    foldM tryOnePing (0, 0) [0 .. 10000]
    

    foldM performs an IO action parametrized by each element of the list and passes some state between iterations, in our case the two counters. It accepts the initial state, and returns the final state. Of course, as its performs IO actions, it returns IO (Int, Int), so we need to use >>= to extract it again for displaying:

    foldM tryOnePing (0, 0) [0 .. 10000] >>= \(c, f) -> print (c, f)
    

    In Haskell, you can perform so called ‘eta reductions’, that is you can remove same identifiers from both sides of a function declaration. E.g. \foo -> bar foo is the same as just bar. So in this case with >>= you can write:

    foldM tryOnePing (0, 0) [0 .. 10000] >>= print
    

    which is much shorter than do notation:

     do
       (c, f) <- foldM tryOnePing (0, 0) [0 .. 10000]
       print (c, f)
    

    Also note that you don’t need to have two counters: if you have 3000 successes then you have 7000 failures. So the code becomes:

    main = do
        conn <- connect "192.168.35.62" 8081
        let tryOnePing c i = do
            p <- ping conn "ping"
            return $ if p == "pong" then c+1 else c
        c <- foldM tryOnePing 0 [0 .. 10000]
        print (c, 10000 - c)
    

    Finally, in Haskell its good to separate IO actions from non-IO code. So it’s better to collect all results from pings into a list and then to count successful pings in it:

    main = do
        conn <- connect "192.168.35.62" 8081
        let tryOnePing i = ping conn "ping"
        pings <- mapM tryOnePing [0 .. 10000]
        let c = length $ filter (\ping -> ping == "pong") pings
        print (c, 10000 - c)
    

    Note that we avoided incrementing altogether.

    It can be written even shorter, but requires more skill to read and write. Don’t worry, you will learn these tricks soon:

    main = do
        conn <- connect "192.168.35.62" 8081
        c <- fmap (length . filter (== "pong")) $ mapM (const $ ping conn "ping") [0 .. 10000]
        print (c, 10000 - c)
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I wanted to make some simple file recovery software, where I want to try
When I try to make a simple module in IntelliJ it responds with: Fatal
I will try to make this simple and quick.. I have never attempted this
I have got a problem when I try to make following simple connections QSpinBox
I'll try and make this question simple. Can I assign a class to a
I'll try to make this as simple as I can. I want to do
I'll try to make this as simple a posible. I just started working with
hey every one I newbie in php and i make simple upload page and
Just as a fun project I wanted to try and make a simple URL
I'm new for rails and ruby. I try to make a simple project and

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.