简体   繁体   English

在单个模式匹配中指定多个替代项?

[英]Specifying multiple alternatives in a single pattern match?

Take the following function as an example (the function is quite meaningless but at least illustrates my question). 以下面的函数为例(该函数毫无意义,但至少说明了我的问题)。

myFunction :: [x] -> x
myFunction [] = "result"
myFunction [x] = "result"
myFunction (_:xs) = myFunction xs
...

Since myFunction [] and myFunction x matches produce the same result, is it possible to combine these into a single pattern-match rather than writing each one on a separate line and cut/pasting the result? 由于myFunction []myFunction x匹配产生相同的结果,是否可以将它们组合成单个模式匹配,而不是将每个写在单独的行上并剪切/粘贴结果? Something like an "OR" operand: 类似于“ OR”操作数:

myFunction [] || x = "result"

Not as such, but there are a couple of alternatives to write it with one clause: 并不是这样,但是有两个替代方法可以用一个子句来编写它:

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

I should tell you that your myFunction doesn't actually typecheck. 我应该告诉您,您的myFunction实际上没有进行类型检查。 It should be like this: 应该是这样的:

myFunction :: [a] -> String
myFunction [] = "result"
myFunction [x] = "result"
myFunction (_:xs) = myFunction xs

That being said, what you want to do can be achieved through guards: 话虽如此,您想做的事情可以通过警卫来实现:

myFunction :: [a] -> String
myFunction xs
  | (null xs) || (length xs == 1) = "result"
  | otherwise = myFunction (tail xs)

Or a more efficient one in which you don't have to traverse the entire list: 或者是一种更高效的方法,您不必遍历整个列表:

 myFunction :: [a] -> String
    myFunction xs
      | (null xs) || null (tail xs) = "result"
      | otherwise = myFunction (tail xs)

How about this? 这个怎么样? Short and sweet: 简短而甜美:

{-# LANGUAGE ViewPatterns #-} 

myFunction ((<2) . length -> True) = "result"
myFunction _ = "other result"

You can replace (<2) . length 您可以替换(<2) . length (<2) . length by any other function of type [a] -> Bool , of course, including lambdas . [a] -> Bool类型的任何其他函数的(<2) . length ,当然包括lambdas As written, your example would probably be more precisely represented with first case 如前所述,您的示例可能用第一种情况更精确地表示

myFunction (\xs -> null xs || length xs == 1 -> True) = "result"
myFunction _ = "other result"

This is breaks for infinite lists, but that shouldn't be too hard to solve. 这是无限列表的突破口,但解决起来并不难。


Finally, if you also enable the LambdaCase extension, you can even write 最后,如果您还启用了LambdaCase扩展程序,甚至可以编写

{-# LANGUAGE ViewPatterns, LambdaCase #-} 

myFunction (\case { []->True ; [x]->True ; _->False } -> True) = "result"
myFunction _ = "other result"

That's getting unreadable and error prone (you have to make sure the \\case expression is total! ) but it does combine two patterns into one, with only constant overhead. 这变得不可读并且容易出错(您必须确保\\case表达式是total!),但是它确实将两种模式组合为一个,而开销却是恒定的。 Don't do this, please :-) 不要这样做,请:-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM