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)
(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"