本文介绍了语法混乱(执行阻止)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对不起,标题不好,请随时进行编辑.我不明白问题是什么,所以可能完全错了.下面是代码(这是在我完成了一百种排列和不同的let-do-if和制表顺序之后,我已经筋疲力尽了):

Sorry for a poor title, feel free to edit. I can't understand what the problem is, so it might be altogether wrong. Below is the code (this is after I've done like a hundred of permutations and different sequences of let-do-if and tabulation, and I'm exhausted):

-- 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的信息,但从我从手册中可以理解的地方,我看不到任何错误.

Something that would meant to be so simple... I still don't understand what is wrong with the code above. Please, if you could kindly explain the source of the error, that would be great.I did read about do, let-in and if-then-else, and I don't see any errors here from what I could understand from the manual.

理想情况下,如果有其他选择,我非常希望减少左侧浪费的空白空间.

Ideally, if there are alternatives, I would like very much to reduce the amount of the wasted white space on the left.

谢谢.

推荐答案

readYear不是Integer,它是一个IO操作,可用于读取输入并将输入转换为整数-在换句话说,IO Integer.而且,由于它是IO动作,因此您需要一个return来使用read year作为getYear的结果.那就是:

readYear is not an Integer, it's an IO action that can be run to read input and convert the input to an integer -- in other words, IO Integer. And as it's an IO action, you'll need a return to use whatever read year as result of getYear. That is:

getYear :: IO Integer
getYear = do year <- getLine
             return (read year)

这也意味着您可以像intYear <- readYear那样使用它,而不是使用let(可以,但是您可以存储IO操作而不是运行它,并且intYear的类型将是错误的).那就是:

This also means you use it like intYear <- readYear instead of using let (well, you could, but you'd store the IO action instead of running it, and the type of intYear would be wrong). That is:

numberOfGoods :: IO String
numberOfGoods = do putStrLn "Enter year (2000-2012):\n"
                   intYear <- readYear
                   ...

do不会扩展到if上,而是如果要在thenelse分支中执行一系列操作,则需要从do重新开始.那就是:

do does not extend over if, rather you need to start again with do if you want a sequence of actions in the then or else branch. That is:

                     else
                            c <- readIORef connection
                            ...
                            return i

应大致为:

                     else do c <- readIORef connection
                             ...
                             return i

关于减少空格,请考虑将验证逻辑放入readYear.实现这一点留给读者练习;)

As for reducing whitespace, consider pushing the validation logic into readYear. Implementing this is left as an exercise to the reader ;)

顺便说一句,当在do块中使用let时,您并不需要in(仅在那里!),您只需声明:

As an aside, you don't need in when using let in a do block (but only there!), you can simply state:

do do_something
   let val = pure_compuation
   something_else_using val

这篇关于语法混乱(执行阻止)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 14:47