Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How do I compare an IO String with a String, print a message if false, and return the value?

I don’t know if this has been asked before, but I haven’t got anywhere from Googling.
I want to have the following code’s equivalent in Haskell:

def inputThing(string: str) -> bool:
  a=input("Input: ")
  if a=="Hello":
    return True
  else:
    print("Not hello")
    return False

What I came up with is something like this:

import System.IO ( hFlush, stdout )
inputThing :: String -> IO Bool
inputThing string = do
  putStr "Input:"
  hFlush stdout
  input <- getLine
  if string == input then True else putStrLn "Not hello" >> False

that last line I simplified to (or rather the linter suggested)

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

(string == input) || (putStrLn "Not hello" >> False)

But I get various errors that all seem to have something to do with things being IO typed or not:

thing.hs:7:3: error:
    • Couldn't match expected type ‘IO Bool’ with actual type ‘Bool’
    • In a stmt of a 'do' block:
        (string == input) || (putStrLn "Not hello" >> False)
      In the expression:
        do putStr "Input:"
           hFlush stdout
           input <- getLine
           (string == input) || (putStrLn "Not hello" >> False)
      In an equation for ‘inputThing’:
          inputThing string
            = do putStr "Input:"
                 hFlush stdout
                 input <- getLine
                 ....
  |
7 |   (string == input) || (putStrLn "Not hello" >> False)
  |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

thing.hs:7:25: error:
    • Couldn't match expected type ‘Bool’ with actual type ‘IO b0’
    • In the second argument of ‘(||)’, namely
        ‘(putStrLn "Not hello" >> False)’
      In a stmt of a 'do' block:
        (string == input) || (putStrLn "Not hello" >> False)
      In the expression:
        do putStr "Input:"
           hFlush stdout
           input <- getLine
           (string == input) || (putStrLn "Not hello" >> False)
  |
7 |   (string == input) || (putStrLn "Not hello" >> False)
  |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

thing.hs:7:49: error:
    • Couldn't match expected type ‘IO b0’ with actual type ‘Bool’
    • In the second argument of ‘(>>)’, namely ‘False’
      In the second argument of ‘(||)’, namely
        ‘(putStrLn "Not hello" >> False)’
      In a stmt of a 'do' block:
        (string == input) || (putStrLn "Not hello" >> False)
  |
7 |   (string == input) || (putStrLn "Not hello" >> False)
  |                                                 ^^^^^

The best I could think of was:

(fmap ((==) string) input) || (putStrLn "Not hello" >> return False)

This still doesn’t work:

thing.hs:7:3: error:
    • Couldn't match expected type ‘IO Bool’ with actual type ‘Bool’
    • In a stmt of a 'do' block:
        (fmap ((==) string) input)
          || (putStrLn "Not hello" >> return False)
      In the expression:
        do putStr "Input:"
           hFlush stdout
           input <- getLine
           (fmap ((==) string) input)
             || (putStrLn "Not hello" >> return False)
      In an equation for ‘inputThing’:
          inputThing string
            = do putStr "Input:"
                 hFlush stdout
                 input <- getLine
                 ....
  |
7 |   (fmap ((==) string) input) || (putStrLn "Not hello" >> return False)
  |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

thing.hs:7:4: error:
    • Couldn't match expected type ‘Bool’ with actual type ‘[Bool]’
    • In the first argument of ‘(||)’, namely
        ‘(fmap ((==) string) input)’
      In a stmt of a 'do' block:
        (fmap ((==) string) input)
          || (putStrLn "Not hello" >> return False)
      In the expression:
        do putStr "Input:"
           hFlush stdout
           input <- getLine
           (fmap ((==) string) input)
             || (putStrLn "Not hello" >> return False)
  |
7 |   (fmap ((==) string) input) || (putStrLn "Not hello" >> return False)
  |    ^^^^^^^^^^^^^^^^^^^^^^^^

thing.hs:7:23: error:
    • Couldn't match type ‘Char’ with ‘[Char]’
      Expected: [String]
        Actual: String
    • In the second argument of ‘fmap’, namely ‘input’
      In the first argument of ‘(||)’, namely
        ‘(fmap ((==) string) input)’
      In a stmt of a 'do' block:
        (fmap ((==) string) input)
          || (putStrLn "Not hello" >> return False)
  |
7 |   (fmap ((==) string) input) || (putStrLn "Not hello" >> return False)
  |                       ^^^^^

thing.hs:7:34: error:
    • Couldn't match expected type ‘Bool’ with actual type ‘IO Bool’
    • In the second argument of ‘(||)’, namely
        ‘(putStrLn "Not hello" >> return False)’
      In a stmt of a 'do' block:
        (fmap ((==) string) input)
          || (putStrLn "Not hello" >> return False)
      In the expression:
        do putStr "Input:"
           hFlush stdout
           input <- getLine
           (fmap ((==) string) input)
             || (putStrLn "Not hello" >> return False)
  |
7 |   (fmap ((==) string) input) || (putStrLn "Not hello" >> return False)
  |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

At this point I thought "Surely there’s a much simpler way of doing this I haven’t thought of" but as previously mentioned, Googling wasn’t getting me far, so I decided to post this.

I am very certain it is the case that you cannot convert an IO String to a String – but I’m guessing there’s a way to get a IO Bool that returns the comparison of an IO String to a String – however, as shown, I didn’t get anywhere with it.

>Solution :

True and False have type Bool, but the result needs to be of type IO Bool. This way, there’s actually an easy and sensible conversion (unlike IO Bool to Bool, which is not possible): this is what return does! So it actually looks more similar to Python:

   if string == input
    then return True
    else putStrLn "Not hello" >> return False

or, depending on your taste in code layout

   if string == input then
       return True
    else do
       putStrLn "Not hello"
       return False

or shorter, applicative-style:

   if string == input
    then pure True
    else False <$ putStrLn "Not hello"
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading