为什么要“做空"?我的工作不为空时出现错误? [英] Why "Empty do" error when my do isn't empty?

查看:45
本文介绍了为什么要“做空"?我的工作不为空时出现错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个菜单,该菜单根据用户输入提供输出.但是,即使在下面有执行代码,我也会得到一个空的do错误.我想念什么吗?

I am trying to create a menu which gives output based on user input. However, I get a empty do error even though I have code for it to do underneath it. Am I missing something?

main :: IO()
main = do 
       contents <- readFile "spa.txt"
       let storage = (read contents :: [Spa])
       putStrLn "Please Enter Your Name: "
       name <- getLine
       putStrLn ""
       putStrLn ("Welcome " ++ name)
       menu storage
       putStrLn ""

       where menu resDB = do
                            putStrLn "\nPlease select an option:"
                            putStrLn "1: Add a new spa to the database "
                            putStrLn "2: Exit"                      
                            putStr "\nSelected option: "
                            putStrLn ""
                            option <- getLine    
                            output :: Int -> IO ()
                            output = do 
                                case option of
                                    1 -> putStrLn "Enter Spa ID: "

推荐答案

这确实是一个缩进问题.让我给出一个可以正确解析并且对眼睛友好的版本:

This is indeed an indentation problem. Let me just give a version that parses correctly and is eye-friendly:

main :: IO ()
main = do 
  contents <- readFile "spa.txt"
  let storage = read contents :: [Spa]
  -- ...
  menu storage
 where menu resDB = do
         putStrLn "~~~" 
         putStrLn "\nPlease select an option:"
         putStrLn "1: Add a new spa to the database "
         -- ...
         option <- getLine    
         putStrLn "~~~"

         output option

       output :: Int -> IO ()
       output option = case option of
         1 -> putStrLn "Enter Spa ID: "

请注意, output 仅缩进到 where 块的级别,而不缩进到 do 块的级别.通常, do 块用于编写语句(单调动作),而不是像您在此处尝试的那样给出声明.您可以始终将声明嵌入在 do 块中,但是您需要将声明放入 let 块中:这也可以,并且可以省略 option 作为 output 的显式参数,因为它们现在位于同一本地范围内:

Note that output is indented only to the level of the where block, not the do block. Generally, do blocks are for writing statements (monadic actions), not for giving declarations like you tried here. You can always embed declarations in a do block, but you need to put them in a let block: this also works, and allows omitting option as an explicit argument to output because they're now inside the same local scope:

 where menu resDB = do
         putStrLn "~~~" 
         option <- getLine    

         let output :: IO ()
             output = case option of
               1 -> putStrLn "Enter Spa ID: "

         output

但是,如果仅定义 output 以便立即将其立即调用一次,那么您还可以完全内联该声明:

But, if you're only defining output in order to immediately invoke it exactly once, then you might as well inline the declaration entirely:

 where menu resDB = do
         putStrLn "~~~" 
         option <- getLine    
         case option of
           1 -> putStrLn "Enter Spa ID: "

根据代码量,命名声明确实有意义.

Depending on the amount of code, a named declaration does make sense though.

您可以进一步减少所需的缩进:这种样式避免了七个空格的缩进的 where 块.我个人不太喜欢它.

You can reduce the needed indentation even more: this style avoids the seven-space indented where block. I personally don't like it as much though.

main :: IO ()
main = do 
  contents <- readFile "spa.txt"
  let storage = read contents :: [Spa]
  -- ...
  menu storage
 where
  menu resDB = do
    putStrLn "~~~" 
    -- ...

菜单 output 也可以在顶层声明(即完全没有缩进),前提是您确实使用显式参数来传递数据.此外,您可以在 output 中使用不同的子句来区分大小写:

And both menu and output could also be declared at the top-level (i.e. with no indentation at all), provided that you do use explicit arguments to pass around the data. Furthermore, you can use just different clauses for that case distinction in output:

main :: IO ()
main = do 
  contents <- readFile "spa.txt"
  menu $ read storage

menu :: [Spa] -> IO ()
menu resDB = do
  putStrLn "~~~" 
  -- ...
  option <- getLine    
  output option

output :: Int -> IO ()
output 1 = putStrLn "Enter Spa ID: "
output 2 = ...

这篇关于为什么要“做空"?我的工作不为空时出现错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆