2012-04-07 11 views
5

Sulla base di altre domande simili, ho scoperto che il mio problema ha a che fare con il rientro, ma ho incasinato molto e ancora non riesco a capirlo su.L'ultima istruzione in un costrutto 'do' deve essere un'espressione Haskell

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 
+0

questo può essere rilevante per gli altri ... Ho avuto la prima riga nel "do" con un rientro tab e il resto con spazi: P –

risposta

18

Nel tuo caso non è indentazione; hai davvero finito la tua funzione con qualcosa che non è un'espressione. yr <- getLine - cosa ti aspettavi di accadere a yr, o per quello aut, dopo questo? Stanno penzolando, non usati.

Può essere più chiaro per mostrare come questo si traduce:

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 -> 

Allora, che cosa si desidera avere dopo che l'ultima freccia?

+1

Inoltre, si potrebbe voler dire che 'getLine' può essere chiamato senza che il suo risultato sia vincolato, anche se probabilmente non è ciò che intendeva. Potrebbe essere sotto l'impressione sbagliata che le cose con un tipo di ritorno diverso da '()' devono essere associate a una variabile. –

7

Pensa al tipo di addBook. È IO a dove a è ... niente. Questo non funziona. La tua monade deve avere qualche risultato.

Si potrebbe desiderare di aggiungere qualcosa di simile alla fine:

return (tit, aut, yr) 

In alternativa, se non si vuole avere qualche risultato utile, restituire una tupla vuota (un'unità):

return() 
+0

awsome! Di te così tanto! – user1319603

+5

@ user1319603: attenzione, 'return' è diverso dalle sue controparti nelle lingue imperative. In Haskell, 'return' è una funzione come qualsiasi altra. Prende un valore di qualche tipo 'a' e lo avvolge in (in questo caso) valore di tipo' IO a'. Prima di apprendere le monadi è meglio usare questa regola empirica: l'ultima cosa nel blocco 'do' deve avere il tipo' IO a' per qualche tipo 'a'. Nel tuo caso, 'yr <- getLine' dovrebbe digitare' String' e questo non è permesso (infatti, avendo la funzione di tipo 'IO a → a' si rompono molte belle proprietà). – Vitus

+1

@ user1319603 È necessario * upvote * (fare clic sulla freccia su per) ogni risposta che ti ha aiutato e * accettare * (fare clic sul segno di spunta per) la risposta che è la migliore o che ti ha aiutato di più. – dave4420

0

rimuovere l'ultima riga dal momento che non è un'espressione, quindi utilizzare le parentesi per le stringhe passate a putStrLn.

1

Se prendete il vostro codice:

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 

e "tradurre" a "normale" (non do) la notazione (dato p = putStrLn "..."):

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

Stai finendo con (yr -> questo non ha senso Se non si dispone di qualsiasi altra cosa utile da fare, si può solo tornare una tupla vuota:

return() 

alla fine:

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

Probabilmente si dovrebbe chiedere perché è necessario per ottenere aut e yr però.

+0

+1 per le parentesi esplicite !!! ... forse 'return (tit, aut, yr)' è anche appropriato ... Inoltre, invece di 'yr <- getLine; return() 'possiamo semplicemente scrivere' getLine' - scegliamo quale dipende da cosa vogliamo "return". –

Problemi correlati