【问题标题】:Haskell: Multiple Case Statements in Single FunctionHaskell:单个函数中的多个 case 语句
【发布时间】:2010-11-22 03:24:16
【问题描述】:

我想在 Haskell 函数中包含多个 case 语句(请参阅下面的假设函数示例)。

但是,它不是合法的 Haskell。有什么更好的方法来完成同样的事情?此外,如果 case 语句没有返回任何内容,而只是设置了一些值,那么为什么在一个函数中包含多个 case 语句是不合法的呢?

(我会在第 5 行收到“输入‘case’时出现解析错误”)

tester x y =  
   case (x < 0) of  
       True -> "less than zero."  
       False -> "greater than or equal to zero."  
   case (y == "foo")  
       True -> "the name is foo."  
       False -> "the name is not foo." 

请注意,如果我的功能很简单:

tester x y =  
   case (x < 0) of  
       True -> "less than zero."  
       False -> "greater than or equal to zero."

...然后它会编译。

【问题讨论】:

  • 一个更详细的例子会有所帮助。如果 x 为 1 且 y 为“foo”,测试器函数应该返回什么?
  • 由于 Haskell 中没有副作用,因此 case 表达式设置某个值而不是返回是没有意义的。你想做什么需要超过 1 个案例陈述?

标签: haskell case-statement


【解决方案1】:

一般the body of a function has to be a single expression(通常由较小的表达式组成)。不允许出现以下情况,例如:

f x y =
  "foo"
  "bar"

这等同于您的第一个示例——我们只是将一种表达式(字符串文字)替换为另一种(您的 case 表达式)。

当然可以在 Haskell 函数中包含多个 case 表达式:

tester :: Int -> String -> (String, String)
tester x y = (a, b)
  where
    a = case (x < 0) of  
          True -> "less than zero."  
          False -> "greater than or equal to zero."  
    b = case (y == "foo") of
          True -> "the name is foo."  
          False -> "the name is not foo."

甚至:

tester :: Int -> String -> IO ()
tester x y = do
  putStrLn $ case (x < 0) of  
               True -> "less than zero."  
               False -> "greater than or equal to zero."  
  putStrLn $ case (y == "foo") of
               True -> "the name is foo."  
               False -> "the name is not foo."

这些工作是因为函数的主体是一个单一的表达式(尽管两者都不是真正地道的 Haskell)。

【讨论】:

    【解决方案2】:

    虽然在这种情况下我不会使用 case 语句,但这个 IMO 看起来更好:

    tester :: Int -> String -> String
    tester x y | x < 0     = "less than zero. " ++ expr
               | otherwise = "greater than or equal to zero. " ++ expr
        where expr = if y == "foo" then "the name is foo." else "the name is not foo." 
    

    【讨论】:

      【解决方案3】:

      一般来说,您想要的是guards。但是,如前所述,您的函数不是单个表达式。假设您要返回一个字符串元组,可以使用守卫这样编写(还有一些来自Arrows 的乐趣):

      import Control.Arrow
      
      testx x | x < 0      = "Less then zero."
              | otherwise  = "Greater then or equal to zero."
      
      testy y | y == "foo" = "The name is foo."
              | otherwise  = "The name is not foo."
      
      tester = curry (testx *** testy)
      

      您也可以将 Control.Arrow 位放在一起并写入:

      tester x y = (testx x, testy y)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-30
        • 1970-01-01
        • 2021-12-11
        • 2011-04-19
        相关资源
        最近更新 更多