Haskell:单个函数中的多个 Case 语句

发布于 2024-10-04 09:28:30 字数 646 浏览 2 评论 0原文

我想在 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."

...那么它将编译。

I want to include more than one case statement in a Haskell function (see below for an example of a hypothetical function).

However, it is not legal Haskell. What is a better way of accomplishing the same thing? Furthermore, if the case statements are not returning anything, but simply setting some value, why is it not legal to have more than one case statement in a function?

(I would get a "parse error on input `case'" on line 5)

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

Note that if my function were simply:

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

...then it would compile.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

何以畏孤独 2024-10-11 09:28:30

一般来说,函数体必须是单个表达式(通常由较小的表达式)。例如,以下内容是不允许的:

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)。

In general the body of a function has to be a single expression (very often made up of smaller expressions). The following isn't allowed, for example:

f x y =
  "foo"
  "bar"

This is equivalent to your first example—we've just substituted one kind of expression (string literals) for another (your case expressions).

It's certainly possible to include more than one case expression in a Haskell function:

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

Or even:

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

These work because the body of the function is a single expression (although neither is really idiomatic Haskell).

死开点丶别碍眼 2024-10-11 09:28:30

不过,在这种情况下我不会使用 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." 

I wouldn't use a case statement in this case though, this IMO looks better:

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." 
沉睡月亮 2024-10-11 09:28:30

一般来说,看起来你想要的是守卫。但是,正如已经提到的,您的函数不是单个表达式。假设您想返回一个字符串元组,可以使用守卫这样编写(以及来自 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)

In general, it looks like what you want is guards. However, as already mentioned, your function is not a single expression. Assuming that you want to return a tuple of strings, it can be written like this using guards (and some added fun from 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)

You could also drop the Control.Arrow bit all together and write:

tester x y = (testx x, testy y)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文