我知道缩进错误是什么,但我不知道为什么我在这里得到这个错误,而每个都是对齐的,试图解决它2个小时。
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"
答案 0 :(得分:8)
问题在于:
-- |<---- "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
块的一部分)读取。
要修复缩进错误,应该是:
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
错误:read
需String
,g :: IO String
g == 1
错误:1
是Int
,但是g :: IO String
show value
错误:show
返回String
,但您将其用作IO
操作Account
的声明,但您可能也会遇到name
和amount
的问题您可能需要以下内容:
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"
基本上,使用v <- expr
从expr :: IO Something
转到v :: Something
。
其他说明:
g <- getLine; let enteredValue = read g :: Int
更好地写为enteredValue <- readLn :: IO Int
putStrLn (show value)
可缩短为print value
do
(单个操作数也不需要$
):... else putStrLn "Nothing"
答案 1 :(得分:4)
您的代码错误而不仅仅是Indentation Errors
- 所以我的第一个建议是阅读learn you a haskell for great good。
接下来haskell中有两个赋值运算符 - 一个 bind 是一个动作… <- …
的结果,另一个是纯计算的本地定义/声明{{1} }。
此外,您可以通过将let … = …
替换为read
来考虑可能的错误输入(有意和无意地),从而改善read
值。后者返回readMaybe
,例如Maybe something
或readMaybe "1" = Just 1 :: Maybe Int
。
关于缩进,最好将一个解决方案与您自己的程序进行比较:
readMaybe "foo" = Nothing :: Maybe Int
此处
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
- 块的下一个if
之后更改范围 -then
- 块不共享每个分支的“声明”,因此您无法在else
- 块中使用name
,但可以使用else
两者。
enteredValue
此处再次
if enteredValue == Just 1 then do putStrLn "Enter your name " name <- getLine putStrLn "Enter the initial amount" amount' <- fmap readMaybe getLine
和name
共享相同的范围,amount'
上的模式匹配会创建一个新的范围,其中amount'
可见且匹配{{1}你无法使用这个变量。
amount
答案 2 :(得分:4)
let
用于绑定值,以let x = y+z
形式完成,其中x
是绑定的名称(也称为“标识符”),y+z
是它被绑定的表达式。
在您的示例中,我看到三个绑定:name
,amount
和value
。其余的不是值绑定,而是操作。
在do
表示法中,操作不需要let
。你只是一个接一个地写它们。所以:
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
是操作。为了使其“运行”并“生成”String
值,您需要使用<-
结构而不是let
:
name <- getLine
与readLn
类似:
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
在解决所有这些问题之后,您在计划的第一部分遇到类似的困难,即let g = getLine
而不是g <- getLine
。