[英]Haskell, how to replace nested if with a case-of statement?
I'm starting to learn haskell and I'm solving some simple programming challenges.我开始学习 Haskell,我正在解决一些简单的编程挑战。 So my current problem right now is just printing some text based on the value being passed:
所以我现在的问题只是根据传递的值打印一些文本:
main = do
n <- readLn :: IO Int
if n `mod` 2 > 0
then putStrLn "Weird"
else if n > 1 && n < 6
then putStrLn "Not Weird"
else if n > 5 && n < 21
then putStrLn "Weird"
else putStrLn "Not Weird"
However I think this is fairly ugly, is there someway I could replace the nested if structure with a more elegant pattern matching?但是我认为这相当丑陋,有没有办法用更优雅的模式匹配替换嵌套的 if 结构?
I've tried:我试过了:
main :: IO()
main = do
n <- readLn :: IO Int
case n of
n `mod` 2 /= 0 -> putStrLn "Weird"
n >= 2 && N <= 5 -> putStrLn "Not Weird"
n >= 6 && N <= 20 -> putStrLn "Weird"
n > 20 -> putStrLn "Not Weird"
but I get a compile error.但我收到编译错误。
Edit: Final solution编辑:最终解决方案
check :: Int -> String
check n
| (n `mod` 2 /= 0) = "Weird"
| (n >= 2) && (n <= 5) = "Not Weird"
| (n >= 6) && (n <= 20) = "Weird"
| otherwise = "Not Weird"
main :: IO()
main = do
n <- readLn :: IO Int
putStrLn (check n)
You need to use guards if you have boolean expressions (conditions), instead of actual patterns.如果您有布尔表达式(条件),而不是实际模式,则需要使用守卫。
main :: IO()
main = do
n <- readLn :: IO Int
case () of
_ | n `mod` 2 /= 0 -> putStrLn "Weird"
| n >= 2 && n <= 5 -> putStrLn "Not Weird"
| n >= 6 && n <= 20 -> putStrLn "Weird"
| n > 20 -> putStrLn "Not Weird"
Consider using otherwise
in the last case: assuming you want to catch everything else, it's faster and suppresses a GHC warning about non-exhaustiveness.考虑在最后一种情况下使用
otherwise
:假设您想捕获其他所有内容,它会更快并抑制关于非穷尽性的 GHC 警告。
A "multiway if" can also be used as an alternative, but it requires an extension. “multiway if”也可以用作替代方案,但它需要扩展。
A case
expression [Haskell-report] deals with patterns. case
表达式[Haskell-report]处理模式。 An expression like n `mod` 2 /= 0
is not a pattern.像
n `mod` 2 /= 0
这样的表达式不是模式。
I propose to define a helper function, and use guards :我建议定义一个辅助函数,并使用guards :
tmp :: Int -> String
tmp n | n `mod` 2 /= 0 = "Weird"
| n >= 2 && N <= 5 = "Not Weird"
| n >= 6 && N <= 20 = "Weird"
| n > 20 = "Not Weird"
| otherwise = …
You will still need to define a value for the otherwise
case, in case n <= 0
.您仍然需要为
otherwise
情况定义一个值,以防n <= 0
。
We can then use this with:然后我们可以将其用于:
main = do
n <- readLn
putStrLn (tmp n)
"multiway if" was mentioned in chi's answer but not explained and I think it's useful to know about for such cases. chi 的回答中提到了“multiway if”,但没有解释,我认为了解这种情况很有用。 Enabling the
MultiWayIf
extension (eg by writing {-# LANGUAGE MultiWayIf #-}
at the top of the file) allows you to write启用
MultiWayIf
扩展(例如通过在文件顶部写入{-# LANGUAGE MultiWayIf #-}
)允许您编写
if | (n `mod` 2 /= 0) -> putStrLn "Weird"
| (n >= 2) && (n <= 5) -> putStrLn "Not Weird"
| (n >= 6) && (n <= 20) -> putStrLn "Weird"
| otherwise -> putStrLn "Not Weird"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.