我想在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."
...然后它会编译。
答案 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)