在单个模式匹配中指定多个备选方案?

时间:2014-10-12 15:59:44

标签: haskell pattern-matching

以下面的函数为例(该函数毫无意义,但至少说明了我的问题)。

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

由于myFunction []myFunction x匹配产生相同的结果,是否可以将它们组合成单个模式匹配,而不是将每个匹配在一个单独的行上并剪切/粘贴结果?类似于" OR"操作数:

myFunction [] || x = "result"

3 个答案:

答案 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表达式是完全的!)但它确实将两种模式合并为一种,只有不变的开销。不要这样做,请: - )