2
votes

I am writing a palindrome solution in Haskell, and I want the function to show an error if a null is entered. I do not want to use the error function as that halts the program. Hence, I want to show an error message using putStrLn and continue the loop.

I have tried using show to change the input given to the putStrLn but it doesn't work and throws compile time type-error.

main = do
    putStrLn "Hey there, What's up! ENTER WORD TO CHECK PALINDROME!"
    word <- getLine
    if null word
        then
            -- putStrLn "This is not a word!"
            main    
    else do
        putStrLn  $ show  $ checkPalindrome word
        main

checkPalindrome w = if reverse w == w then True else False

I expect it to show an error, but it only gives an error. What are possible solutions to show a halt-safe error?

1
I expect it to show an error, but it only gives an error. I have no idea what you mean here. Do you get an error when compiling this, or at run time? Or does it run without error but do something unexpected?Robin Zigmond

1 Answers

3
votes

If you write both a putStrLn "this is not a word!" and a main, you should use a do block here:

main = do
    putStrLn "Hey there, What's up! ENTER WORD TO CHECK PALINDROME!"
    word <- getLine
    if null word
        then do
            putStrLn "This is not a word!"
            main    
    else do
        putStrLn  $ show $ checkPalindrome word
        main

That being said, you can simplify the above by making a call at the bottom of the do block of the main:

main = do
    putStrLn "Hey there, What's up! ENTER WORD TO CHECK PALINDROME!"
    word <- getLine
    if null word
        then putStrLn "This is not a word!"
        else putStrLn  $ show $ checkPalindrome word
    main

or we can, like @Bergi says, even put more in the main block, like:

main = do
    putStrLn "Hey there, What's up! ENTER WORD TO CHECK PALINDROME!"
    word <- getLine
    putStrLn $ if null word
        then "This is not a word!"
        else show $ checkPalindrome word
    main

If you write this without do block, Haskell aims to parse putStrLn "This is not a word!" main. This thus means that putStrLn is supposed to have type String -> IO a -> IO a, but that is not the case.

By using a do block, Haskell will desugar the do block [Haskell'10 report] into putStrLn "This is not a word!" >> main, and this is sound (at least for the type system). Since the bind operator has type (>>) :: Monad m => m a -> m b -> m b.