[英]Syntax confusion (do block)
抱歉标题很差,随时可以编辑。 我无法理解问题是什么,所以可能完全错了。 下面是代码(这是在我完成了一百个排列和不同的let-do-if和制表序列之后,我已经筋疲力尽了):
-- The last statement in a 'do' construct must be an expression
numberOfGoods :: IO String
numberOfGoods = do putStrLn "Enter year (2000-2012):\n"
let intYear = readYear
in if (intYear < 2000 || intYear > 2012)
then error "Year must be withing range: 2000-2012"
else
c <- readIORef connection
[Only i] <- query_ c ("select count('*')" ++
"from table" ++
"where ((acquisition_date <= " ++
(formatDate intYear) ++
") and ((sale_date is null) or " ++
"(sale_date < " ++
(formatDate intYear) ++ ")))")
return i
readYear :: Integer
readYear = do
year <- getLine
read year :: Integer
有些事情本来就是这么简单......我仍然不明白上面的代码有什么问题。 如果您能够解释错误的来源,那就太好了。 我确实读过关于do,let-in和if-then-else的内容,而且我从手册中可以理解的内容中没有看到任何错误。
理想情况下,如果有替代方案,我非常希望减少左侧浪费的空白区域的数量。
谢谢。
readYear
不是Integer
,它是一个IO
动作,可以运行以读取输入并将输入转换为整数 - 换句话说, IO Integer
。 因为这是一个IO
动作,你需要return
使用任何read year
作为getYear
结果。 那是:
getYear :: IO Integer
getYear = do year <- getLine
return (read year)
这也意味着你像intYear <- readYear
一样使用它而不是使用let
(嗯,你可以,但你要存储IO动作而不是运行它,而intYear
的类型是错误的)。 那是:
numberOfGoods :: IO String
numberOfGoods = do putStrLn "Enter year (2000-2012):\n"
intYear <- readYear
...
do
没有遍布if
,而你需要重新开始do
,如果你想在动作序列then
或else
分支。 那是:
else
c <- readIORef connection
...
return i
应粗略地说:
else do c <- readIORef connection
...
return i
至于减少空格,请考虑将验证逻辑推入readYear
。 实现这个是留给读者的练习;)
顺便说一句,你不需要in
do
块中使用let
(但只在那里!),你可以简单地说:
do do_something
let val = pure_compuation
something_else_using val
对于每个monadic函数块,你需要一个新的do
:简单地连续编写函数没有任何意义,无论它们是monadic还是pure。 价值来自IO
monad的所有东西都必须在monad中给出它的返回值。
numberOfGoods :: IO String
numberOfGoods = do putStrLn "Enter year (2000-2012):\n" -- why extra '\n'?
intYear <- readYear -- readYear expects user input <- must be monadic
if (intYear < 2000 || intYear > 2012)
then error "Year must be withing range: 2000-2012"
else do
c <- readIORef connection
[Only i] <- query_ c ("select count('*')" ++
"from table" ++
"where ((acquisition_date <= " ++
(formatDate intYear) ++
") and ((sale_date is null) or " ++
"(sale_date < " ++
(formatDate intYear) ++ ")))")
return i
readYear :: IO Integer
readYear = do
year <- getLine
return $ read year :: Integer
do
需要...
好吧,在Haskell中do
的事情就是它真的只是语法糖。 让我们简化一下你的功能吧
nOG :: IO String nOG = do putStrLn "Prompt" someInput <- inputSth if condition someInput then error "Bloap" else do c <- inputSthElse [only] <- query_ c return only
这实际意味着什么
nOG :: IO String nOG = putStrLn "Prompt" >> inputSth >>= (\\someInput -> if condition someInput then error "Bloap" else inputSthElse >>= (\\s -> query_ c >>= (\\[only] -> return only ) ) )
你应该能够看到, if
行为方式与纯函数表达式(如shade (r,g,b) = if g>r && g>b then "greenish" else "purpleish"
完全相同shade (r,g,b) = if g>r && g>b then "greenish" else "purpleish"
。 它不会以任何方式“知道”周围发生的所有IO
monad内容,因此它无法推断其中一个分支中应该再有一个do
块。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.