user1319603
user1319603

Reputation: 765

The last statement in a 'do' construct must be an expression Haskell

Based on other similar questions I found I figure my problem has to do with indentation, but I've messed with it a lot and still can't figure it out.

addBook = do
    putStrLn "Enter the title of the Book"
    tit <- getLine
    putStrLn "Enter the author of "++tit
    aut <- getLine
    putStrLn "Enter the year "++tit++" was published"
    yr <- getLine

Upvotes: 6

Views: 4673

Answers (4)

Shoe
Shoe

Reputation: 76240

If you take your code:

addBook = do
    putStrLn "Enter the title of the Book"
    tit <- getLine
    putStrLn "Enter the author of "++tit
    aut <- getLine
    putStrLn "Enter the year "++tit++" was published"
    yr <- getLine

and "translate" it to "normal" (non-do) notation (given p = putStrLn "..."):

addBook = 
    p >> getLine >>= (\tit ->
        p >> getLine >>= (\aut ->
            p >> getLine >>= (yr ->

You are ending up with (yr -> that doesn't make sense. If you don't have anything else useful to do, you can just return an empty tuple:

return ()

at the end:

addBook = do
    putStrLn "Enter the title of the Book"
    tit <- getLine
    putStrLn "Enter the author of "++tit
    aut <- getLine
    putStrLn "Enter the year "++tit++" was published"
    yr <- getLine
    return ()

You should probably ask yourself why you need to get aut and yr though.

Upvotes: 2

MJ89
MJ89

Reputation: 1

remove the last line since it's not an expression, then use parenthesis for the strings you pass to putStrLn.

Upvotes: 0

geekosaur
geekosaur

Reputation: 61369

In your case it's not indentation; you really have finished your function with something that is not an expression. yr <- getLine — what did you expect to happen to yr, or for that matter aut, after this? They're just dangling, unused.

It may be clearer to show how this translates:

addBook = putStrLn "Enter the title of the Book" >>
          getLine >>= \tit ->
          putStrLn "Enter the author of "++ tit >>
          getLine >>= \aut ->
          putStrLn "Enter the year "++tit++" was published" >>
          getLine >>= \yr ->

So, what did you want to have following that last arrow?

Upvotes: 19

icktoofay
icktoofay

Reputation: 128993

Think about the type of addBook. It's IO a where a is... nothing. That doesn't work. Your monad must have some result.

You might want to add something like this at the end:

return (tit, aut, yr)

Alternatively, if you don't want to have any useful result, return an empty tuple (a unit):

return ()

Upvotes: 8

Related Questions