哈斯克尔,如何用大小写语句替换嵌套?



我开始学习Haskell,我正在解决一些简单的编程挑战。所以我现在的问题只是根据传递的值打印一些文本:

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"

但是我认为这相当丑陋,有没有办法用更优雅的模式匹配替换嵌套的 if 结构?

我试过:

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"

但是我收到编译错误。

编辑:最终解决方案

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)

如果您有布尔表达式(条件(,则需要使用守卫,而不是实际模式。

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"

考虑在最后一种情况下使用otherwise:假设你想捕获其他所有内容,它更快,并抑制有关非详尽性的 GHC 警告。

"多路如果"也可以用作替代方案,但它需要扩展。

case表达式[Haskell-report] 处理模式。像n `mod` 2 /= 0这样的表达式不是模式。

我建议定义一个辅助函数,并使用守卫

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 = …

您仍然需要为otherwise情况定义一个值,以防万一n <= 0

然后我们可以将其用于:

main = do
n <- readLn
putStrLn (tmp n)

chi 的回答中提到了"multiway if",但没有解释,我认为了解这种情况很有用。启用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"

最新更新