2017-12-18 4 views
0

Ich weiß, was ein Einzug Fehler ist, aber ich habe keine Ahnung, warum ich diesen Fehler hier bekomme, während jeder ausgerichtet ist, versuchen, es für 2 Stunden zu lösen.Let Block gibt Eindruck Fehler

Account.hs:40:25: error: 
    parse error (possibly incorrect indentation or mismatched brackets) 
    | 
40 |       let amount = readLn :: IO Int 
    |      ^
Failed, 0 modules loaded. 
main = do 
      putStrLn $ "Press one to create a new account" 
      let g = getLine 
       enteredValue = read g :: Int 
      if g == 1 
       then do putStrLn $ "Enter your name " 
         let name = getLine 
          putStrLn $ "Enter the initial amount" 
          let amount = readLn :: IO Int 
           value = Account (name,1,amount) Saving 
           show value 
       else do putStrLn $ "Nothing" 

Ich habe auch versucht, diese Version aber das gibt auch incorrect indentation or mismatched brackets:

main = do 
     putStrLn $ "Press one to create a new account" 
     let g = getLine 
      enteredValue = read g :: Int 
     if g == 1 
      then do putStrLn $ "Enter your name " 
        let name = getLine 
         putStrLn $ "Enter the initial amount" 
         amount = readLn :: IO Int 
         value = Account (name,1,amount) Saving 
         show value 
      else do putStrLn $ "Nothing" 
+3

BTW. Bitte verwende keine Bilder, um 'text' -basierte Informationen anzuzeigen - kopiere einfach die Fehlermeldung und füge sie wie deinen Quellcode ein. Es ist einfacher für Suchmaschinen, Ihre Inhalte zu indizieren und es stellt Ihre Frage in sich abgeschlossen, wenn der Hosting-Service Ihres Bildes die Frage nicht beantwortet, kann nicht beantwortet werden. – epsilonhalbe

Antwort

8

Das Problem ist hier:

--     |<---- "column 0" of this 'do' block 
      then do putStrLn $ "Enter your name " 
--     | still good; a 'let' statement: 
        let name = getLine 
--      |<---- "column 0" of this 'let' block 
         putStrLn $ "Enter the initial amount" 
--      | Huh, there's no '=' in ^this^ declaration? 
         let amount = readLn :: IO Int 
--      ^^^ Why is there a 'let' within another let binding? 
--       I still haven't seen a '='. Better throw a parse error. 

Grundsätzlich ist putStrLn $ "Enter the initial amount" mit name = ... in der vorangehenden Zeile ausgerichtet sind, so dass der Compiler liest es als eine Erklärung (Teil desselben let Block).

Ihre Einbuchtung Fehler zu beheben, sollte es sein:

main = do 
      putStrLn $ "Press one to create a new account" 
      let g = getLine 
       enteredValue = read g :: Int 
      if g == 1 
       then do putStrLn $ "Enter your name " 
         let name = getLine 
         putStrLn $ "Enter the initial amount" 
         let amount = readLn :: IO Int 
          value = Account (name,1,amount) Saving 
         show value 
       else do putStrLn $ "Nothing" 

Aber dann werden Sie in Art Fehler laufen:

  • read g ist falsch: read eine String nimmt, aber g :: IO String
  • g == 1 ist falsch: 1 ist ein Int, aber g :: IO String
  • show value ist falsch: show ein String zurückgibt, aber Sie verwenden sie als IO Aktion
  • Sie haben nicht die Deklaration von Account gezeigt, aber Sie gehen zu wahrscheinlich Probleme haben mit name und amount auch

Sie wollen wahrscheinlich so etwas wie:

main = do 
      putStrLn $ "Press one to create a new account" 
      g <- getLine 
      let enteredValue = read g :: Int 
      if enteredValue == 1 
       then do putStrLn $ "Enter your name " 
         name <- getLine 
         putStrLn $ "Enter the initial amount" 
         amount <- readLn :: IO Int 
         let value = Account (name,1,amount) Saving 
         putStrLn (show value) 
       else do putStrLn $ "Nothing" 

, Grundsätzlich v <- expr von expr :: IO Something zugehen verwenden.

Andere Anmerkungen:

  • g <- getLine; let enteredValue = read g :: Int besser geschrieben als enteredValue <- readLn :: IO Int
  • putStrLn (show value) kann
  • Sie nicht brauchen do für einen einzelnen Ausdruck (noch $ für einen einzelnen Operanden) zu print value verkürzt werden: ... else putStrLn "Nothing"
3

Es zu Ihrem Code falsch ist, als nur die Indentation Errors - so mein erster Vorschlag eine würde das Lesen Bit von learn you a haskell for great good.

Weiter gibt es zwei Zuweisungsoperator in Haskell - one bind s das Ergebnis einer Aktion … <- … und die andere ist eine lokale Definition/Deklaration einer reinen Berechnung let … = ….

Außerdem können Sie verbessern Ihre read Wert ing unter Berücksichtigung der möglichen falschen Eingabe nehmen, dass jemand, den Sie geben könnte (absichtlich und unabsichtlich) durch read mit readMaybe ersetzt, wobei die letztere liefert einen Maybe something, zum Beispiel readMaybe "1" = Just 1 :: Maybe Int oder readMaybe "foo" = Nothing :: Maybe Int .

In Bezug auf Ihre Einbuchtung ist es am besten, die Sie mit Ihnen eine Lösung für Ihr Programm vergleichen own:

import Text.Read (readMaybe) 

data Type = Saving | Checking 
    deriving (Show) 

data Account = Account (String,Int,Int) Type 
    deriving (Show) 

main :: IO() 
main = do 
     putStrLn "Press one to create a new account" 
     g <- getLine 
     let enteredValue = readMaybe g :: Maybe Int 

hier das Ergebnis getLine und eingegebene Wert haben den gleichen Umfang, so dass sie die gleiche Vertiefung haben - Wir ändern nur den Bereich nach dem nächsten if wo der then -block - und der else -block nicht die 'Deklarationen' jeder Verzweigung teilen, so dass Sie name im else -block nicht verwenden konnten, aber enteredValue kann in verwendet werden beide.

 if enteredValue == Just 1 
      then do putStrLn "Enter your name " 
        name <- getLine 
        putStrLn "Enter the initial amount" 
        amount' <- fmap readMaybe getLine 

hier wieder name und amount' der gleiche Umfang und Muster auf amount' Anpassung schaffen einen neuen Bereich, wo amount sichtbar ist und das Spiel auf Nothing wo Sie diese Variable nicht verwenden können.

    case amount' of 
         Just amount -> print $ Account (name,1,amount) Saving 
         Nothing -> putStrLn "Nothing" 
      else putStrLn "Nothing" 
3

let steht für bindende Werte, was in der Form let x = y+z erfolgt, wobei x der Name (auch bekannt als "Bezeichner") gebunden ist und y+z der Ausdruck ist, an den er gebunden wird. In Ihrem Beispiel sehe ich drei Bindungen: name, amount und value. Der Rest sind keine Wertbindungen, sondern Aktionen.

In der Notation do benötigen Aktionen keine let. Sie schreiben sie einfach nacheinander. Also:

let name = getLine 
putStrLn $ "Enter the initial amount" 
let amount = readLn :: IO Int 
let value = Account (name,1,amount) Saving 
show value 

Aber warte! Das ist nicht alles!

getLine ist eigentlich kein Ausdruck des Typs String, wie Sie hier zu hoffen scheinen. Vielmehr ist getLine eine Aktion.Um es zu bekommen, um "run" und "Produkte" ein String Wert, müssen Sie das <- Konstrukt statt let verwenden:

name <- getLine 

Ähnlich ist es mit readLn:

amount <- readLn :: IO Int 

Schließlich show value ist nicht wirklich eine Aktion, die den Wert auf den Bildschirm drucken würde. show ist eine Funktion, die einen Wert annimmt und eine String zurückgibt. Es "tut" nichts (d. H. Erzeugt keine äußeren Effekte), so dass Sie es nicht anstelle einer Aktion in der Notation do verwenden können. Wenn Sie eine Aktion wollte, die einen Wert auf dem Bildschirm gedruckt werden würde, wäre das print:

print value 

alles Versammeln:

name <- getLine 
putStrLn $ "Enter the initial amount" 
amount <- readLn :: IO Int 
let value = Account (name,1,amount) Saving 
print value 

Und nach all dem Fixieren, müssen Sie ähnliche Schwierigkeiten mit dem ersten Teil Ihres Programms, wo Sie let g = getLine anstelle von g <- getLine haben.