Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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
like image 371
user1319603 Avatar asked Apr 07 '12 21:04

user1319603


3 Answers

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?

like image 77
geekosaur Avatar answered Oct 15 '22 03:10

geekosaur


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 ()
like image 35
icktoofay Avatar answered Oct 15 '22 04:10

icktoofay


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.

like image 2
Shoe Avatar answered Oct 15 '22 04:10

Shoe