2017-12-18 19 views
0

インデントエラーが何であるかは知っていますが、ここでこのエラーが発生する理由は何もわかりません。ブロックでインデントエラーが発生する

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" 

私はまた、このバージョンを試してみましたが、これも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。画像を使って 'テキスト'ベースの情報を表示しないでください。エラーメッセージをコピーしてコピーして、ソースコードのように追加してください。検索エンジンがあなたのコンテンツのインデックスを作成することは簡単です。あなたの写真のホスティングサービスが質問の答えが理解できない場合は、自己完結型の質問になります。 – epsilonhalbe

答えて

8

問題はここにあります。

あなたのインデントのエラーを修正するには、それは次のようになります。

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" 

しかし、その後、あなたは型エラーに遭遇します:

  • read gが間違っている:readStringがかかりますが、g :: IO String
  • g == 1が間違っています:1Intですが、g :: IO String
  • show value間違っている:Stringを返しますが、あなたはAccountの宣言を示していないが、あなたはおそらくあまりにも
  • nameamountの問題を持っているつもりだ IOアクション
  • としてそれを使用しているshow

あなたはおそらく何かしたい:へexpr :: IO Somethingから行くためにv <- exprを使用して、基本的に

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" 

を。

その他の注意事項:

  • g <- getLine; let enteredValue = read g :: Int良くenteredValue <- readLn :: IO Int
  • putStrLn (show value)として書かれたあなたは(単一オペランドにも$)単一の発現のためのdoを必要としないprint value
  • に短縮することができます。... else putStrLn "Nothing"
3

だけIndentation Errorsよりもあなたのコードにより間違ってあります - ので、私の最初の提案は読んでしまいます​​のビット。

次に2つの代入演算子はHaskellである - オンバインドアクション​​の結果だと他の一つは、純粋な計算let … = …のローカル定義/宣言です。

また、あなたのreadは後者を例readMaybe "1" = Just 1 :: Maybe IntまたはreadMaybe "foo" = Nothing :: Maybe Intため、Maybe somethingを返すところ、誰かがreadMaybereadを置き換えることによって、(意図的と意図せずに)あなたを与えることができることを、可能な誤った入力を考慮して値をINGのを向上させることができます。

あなたのインデントについては、それはあなたがあなたとあなたのプログラムへの1つのソリューションを所有して比較することが最善です:

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

getLineと入力された値の結果、彼らは同じインデントを持っているので、同じスコープを持っています - thenブロックとelseブロックが各ブランチの '宣言'を共有しないため、elseブロックでnameを使用できない次のifの後にスコープを変更しますが、enteredValueはどちらも。

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

nameamount'同じスコープを共有し、amount'にパターンマッチングはamountが見える、あなたはこの変数を使用することはできませんNothingに一致する新しいスコープを作成します。

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

基本的に、putStrLn $ "Enter the initial amount"は前ラインにおけるname = ...と整列されているので、コンパイラは、(同じletブロックの一部)宣言として読み取る:

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

letは、値がlet x = y+zの形式で行われる値のバインド用です。ここで、xはバインドされている名前(別名「識別子」)であり、y+zはバインドされている式です。

例では、name,amountvalueという3つのバインディングがあります。残りはバリューバインディングではなく、アクションです。

doの表記では、アクションにはは必要ありません。あなたはちょうどそれらを次々に書きます。だから:

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

待って!これはすべてではありません!

getLineは実際にはタイプStringの表現ではありませんが、ここで期待しているようです。むしろ、getLineは、アクションです。"RUN" にそれを取得し、String値を "作る" ためには、あなたの代わりにlet<-構文を使用する必要があります:readLnと同様に

name <- getLine 

を:

amount <- readLn :: IO Int 

最後に、show valueがあります実際に値を画面に表示するアクションではありません。 showは、値をとり、Stringを返す関数です。何もしていない(つまり、外的な影響はありません)ので、doという表記法の代わりに使用することはできません。あなたが画面に値を印刷しアクションを望んでいた場合、それはprint次のようになります。

print value 

一緒にすべてを収集:

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

そして、それのすべてを固定した後、あなたが持っているだろうしあなたのプログラムの最初の部分で同様の問題がありました。g <- getLineの代わりにlet g = getLineがあります。

関連する問題