Search code examples
haskellif-statementlet

How to use let inside if block inside a do notation in haskell


I'm getting an error with the following code:

main = do
    putStrLn "Enter parameter"
    parameter <- getLine
    if head parameter == "c" then
        let object = getObject parameter
        print object
    else
        putStrLn "Error, try again"
        main

The error I get is:

parse error on input `print'

when trying to print the object. If I instead try to print the value of the function without saving it with let it works just fine, but I need to save the object for later use.

How should the syntax be to make it work?

Also in the "else" part I get the following error:

The function `putStrLn' is applied to two arguments,
    but its type `String -> IO ()' has only one
    In the expression: putStrLn "Error" main

It thinks I try to run main as a parameter to putStrLn, but what I really want to do is first show the error and then run main again. How can I fix this?

Thanks in advance!


Solution

  • There's a few issues with your code.

    Firstly, there's the parse error. There's two ways to fix this. One is by using a let .. in block, as @Lee points out.

    let object = getObject parameter
    in  print object
    

    Alternatively, we can just start another do block in the else clause:

    then do
       let object = getObject parameter
       print object
    

    Secondly, you're comparing the head of a string, to another string:

    head parameter == "c"

    getLine returns a string, so the head of a string is a character. We can just change this to

    head parameter == 'c'

    And finally, you're trying to do two statements in one block, similar to before in your else clause:

    else 
        putStrLn "Error, try again"
        main
    

    If you want to chain together multiple statements, we have to use a do block, as before:

    else do
        putStrLn "Error, try again"
        main
    

    Putting it all together:

    main = do
        putStrLn "Enter parameter"
        parameter <- getLine
        if head parameter == 'c' then do
            let object = getObject parameter
            print object
        else do
            putStrLn "Error, try again"
            main