当我的 do 不为空时,为什么会出现“Empty do”错误?

2024-01-27

我正在尝试创建一个菜单,该菜单根据用户输入提供输出。但是,即使我有代码可以在其下面执行操作,我也会收到一个空的 do 错误。我错过了什么吗?

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

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

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块用于写入声明(一元行动),不是为了给予声明就像你在这里尝试过的那样。你can始终将声明嵌入do块,但你需要将它们放入letblock:这也有效,并且允许省略option作为一个明确的论据output因为它们现在位于同一本地范围内:

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

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

         output

但是,如果你只是定义output为了立即调用它一次,那么您不妨完全内联声明:

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

不过,根据代码量,命名声明确实有意义。

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

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

还有两个menu and output也可以在顶层声明(即根本没有缩进),前提是您确实使用显式参数来传递数据。此外,您可以使用不同的子句来区分情况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 = ...
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当我的 do 不为空时,为什么会出现“Empty do”错误? 的相关文章

  • 无点镜头创建不进行类型检查

    在函数中test 我遍历一个列表 从它的成员生成镜头 然后打印一些数据 当我使用有针对性的呼叫风格时 这会起作用 当我使其成为无点时 它无法进行类型检查 为什么会出现这种情况 我该如何解决这个问题 在我看来 GHC 并没有保留排名较高的信息
  • Haskell scala 互操作性

    我是 Scala 初学者 来自面向对象范式 在了解 Scala 的函数式编程部分时 我被引导到 Haskell 纯函数式编程语言 探索 SO 问题答案 我发现 Java Haskell 具有互操作性 我很想知道 Scala Haskell
  • 在 Haskell 中,为什么我必须在这段代码中使用美元符号?

    我仍在尝试破解这段代码 import Data Char groupsOf groupsOf n xs take n xs groupsOf n tail xs problem 8 x maximum map product groupsO
  • Haskell:是的,没有类型类。为什么是整数?

    我有一个关于 GHCi 如何假定整数类型的问题 我正在阅读 Learn you a Haskell 是 否类型的课程 如果您想阅读全文 这里有一个链接 http learnyouahaskell com making our own typ
  • 搜索重写规则

    有什么办法可以浏览或搜索重写规则吗 当我使用像这样的标志时 ddump rule firings or ddump rule rewrites我只是得到了触发的规则的名称以及它引起的重写 但没有得到实际的规则本身 理想情况下 我想通过 GH
  • 在依赖类型的函数式编程语言中,扁平化列表是否更容易?

    在 haskell 中寻找一个可以展平任意深度嵌套列表的函数时 即应用的函数concat递归并在最后一次迭代时停止 使用非嵌套列表 我注意到这需要有一个更灵活的类型系统 因为随着列表深度的变化 输入类型也会变化 确实 有几个 stackov
  • 将 num 的签名键入 double?

    我才刚刚开始为你学习 Haskell 以获得伟大的好处 并且我在类型类方面遇到了一些麻烦 我想创建一个接受任何数字类型并强制其为双精度的函数 我的第一个想法是定义 numToDouble Num gt Double 但我认为这不起作用 因为
  • Haskell,堆栈:找到可执行文件

    我正在寻找类似的东西 stack whereis hasktags where whereis行为或多或少类似于 UNIXwhereis命令 hasktags是这样运行的 stack exec hasktags stack exec whe
  • 规范化且不可变的数据模型

    Haskell如何解决 规范化不可变数据结构 问题 例如 让我们考虑一个表示前女友 男友的数据结构 data Man Man name String exes Woman data Woman Woman name String exes
  • “Eta减少”并不总是在Haskell中举行?

    我发现我可以说 LANGUAGE RankNTypes f1 forall b b gt b gt forall c c gt c f1 f id f HLint 告诉我我可以在这里做 Eta 减少 但是 f2 forall b b gt
  • Haskell 中的中缀运算符优先级

    对于以下 Haskell 表达式 返回 a gt gt f 应该读作 返回a gt gt f or 返回 a gt gt f 这里的相关规则是什么 规则始终是函数应用程序的优先级高于任何运算符 因此 return a gt gt f 被解析
  • Haskell / GHC - 是否有“警告不完整模式”的中缀标签/编译指示

    我正在寻找一个可以对特定的不完整模式发出警告的编译指示 它会使编译器失败并显示以下 假设的 代码 FAILIF incomplete patterns f Int gt Int f 0 0 我正在尝试使用 Arrows 编写一个 编译器 并
  • Haskell Stack 从 github 安装包依赖项

    是否可以使用 Haskell 堆栈从 github 安装软件包的版本 例如在一个 cabal or a stack yaml文件 如何在 git repo branch revision 上指向依赖项 对于堆栈 The 的文档stack y
  • 找不到模块“Yesod”

    我有以下代码 LANGUAGE TypeFamilies QuasiQuotes MultiParamTypeClasses TemplateHaskell OverloadedStrings module Simple where imp
  • Haskell - lambda 表达式

    我试图了解什么是有用的以及如何在 Haskell 中实际使用 lambda 表达式 我不太明白使用 lambda 表达式相对于定义函数的约定方式有何优势 例如 我通常会执行以下操作 let add x y x y 我可以简单地打电话 add
  • 如何通过“cabal build”或“stack build”构建带有图标的项目

    我想构建一个带有图标的可执行文件 通过谷歌搜索 我发现这里的说明 https wiki haskell org Setting an executable icon 但它只能通过编译源文件来工作ghc 如果我想构建一个具有可执行文件的项目c
  • 如何在不声明新数据的情况下更改类型(String,Int)元组的 Ord 实例?

    我正在尝试对类型列表进行排序 String Int 默认情况下 它按字符串排序 然后按整数排序 如果字符串相等 我希望它是相反的 首先比较整数 然后如果相等则比较字符串 另外 我不想切换到 Int String 我找到了一种通过定义实例来实
  • 如何更换HXT中的节点?

    给定一个示例 xml 文件
  • Haskell:对 Num 类型类的使用感到困惑

    我很困惑为什么这有效 f Num a gt a gt a f x x 42 但这并没有 g Num a gt a gt a g x x 4 2 我本来就明白Num包含实现运算符的所有类型 因此 如果42 is an Int and 4 2
  • 在 ghci 下执行 `(read "[Red]") :: [Color]` 时会发生什么?

    我正在阅读以下小节现实世界 Haskell 第 6 章 类型类 http book realworldhaskell org read using typeclasses html关于一个实例Read for Color 它实现了reads

随机推荐