以下面的函数为例(该函数毫无意义,但至少说明了我的问题)。
myFunction :: [x] -> x
myFunction [] = "result"
myFunction [x] = "result"
myFunction (_:xs) = myFunction xs
...
由于myFunction []
和myFunction x
匹配产生相同的结果,是否可以将它们组合成单个模式匹配,而不是将每个匹配在一个单独的行上并剪切/粘贴结果?类似于" OR"操作数:
myFunction [] || x = "result"
答案 0 :(得分:3)
不是这样,但有几种方法可以用一个子句写出来:
myFunction' (_:xs@(_:_)) = foo xs -- note the changed order: `_:...` first, thus
myFunction' _ = "result" -- you'll get "result" for _every_ other input
myFunction'' xs | null $ drop 1 xs = "result" -- or `| [] <- drop 1 xs`
myFunction'' (_:xs) = foo xs
myFunction''' xs' = case drop 1 xs' of
[] -> result
xs -> foo xs
答案 1 :(得分:2)
我应该告诉你,你的myFunction
实际上并没有进行类型检查。它应该是这样的:
myFunction :: [a] -> String
myFunction [] = "result"
myFunction [x] = "result"
myFunction (_:xs) = myFunction xs
话虽这么说,你想做的事情可以通过警卫来实现:
myFunction :: [a] -> String
myFunction xs
| (null xs) || (length xs == 1) = "result"
| otherwise = myFunction (tail xs)
或者更有效的一个,你不必遍历整个列表:
myFunction :: [a] -> String
myFunction xs
| (null xs) || null (tail xs) = "result"
| otherwise = myFunction (tail xs)
答案 2 :(得分:1)
这个怎么样?简短又甜蜜:
{-# LANGUAGE ViewPatterns #-}
myFunction ((<2) . length -> True) = "result"
myFunction _ = "other result"
您可以使用(<2) . length
类型的任何其他函数替换[a] -> Bool
,当然,包括lambdas 。如上所述,您的示例可能会更准确地用第一种情况表示
myFunction (\xs -> null xs || length xs == 1 -> True) = "result"
myFunction _ = "other result"
这是无限列表的中断,但这不应该太难解决。
最后,如果您还启用LambdaCase
扩展程序,则甚至可以编写
{-# LANGUAGE ViewPatterns, LambdaCase #-}
myFunction (\case { []->True ; [x]->True ; _->False } -> True) = "result"
myFunction _ = "other result"
它变得难以理解并且容易出错(你必须确保\case
表达式是完全的!)但它确实将两种模式合并为一种,只有不变的开销。不要这样做,请: - )