Haskell:单函数中的多个案例陈述

时间:2010-11-22 03:24:16

标签: haskell case-statement

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

...然后它会编译。

3 个答案:

答案 0 :(得分:10)

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

f x y =
  "foo"
  "bar"

这相当于你的第一个例子 - 我们只是将一种表达式(字符串文字)替换为另一种表达式(你的案例表达式)。

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

答案 1 :(得分:3)

我不会在这种情况下使用案例陈述,但这个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." 

答案 2 :(得分:2)

一般来说,看起来你想要的是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)