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

Haskell 在单个模式匹配中指定多个备选方案?,haskell,pattern-matching,Haskell,Pattern Matching,以下面的函数为例(该函数很无意义,但至少说明了我的问题) 由于myFunction[]和myFunction x匹配产生相同的结果,是否可以将它们组合成一个模式匹配,而不是将每个模式都写在单独的行上并剪切/粘贴结果?类似于“或”操作数: 不是这样的,但是有两种方法可以用一个条款来写: myFunction' (_:xs@(_:_)) = foo xs -- note the changed order: `_:...` first, thus myFunction' _ = "result"

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

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


不是这样的,但是有两种方法可以用一个条款来写:

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
myFunction'(:xs@(:)))=foo-xs——注意更改的顺序:`:…`首先,因此
myFunction'\u=“result”--每隔一次输入都会得到“result”

myFunction“”xs | null$drop 1 xs=“result”--或“|[]并非如此,但有两种方法可以使用一个子句编写它:

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
myFunction'(:xs@(:)))=foo-xs——注意更改的顺序:`:…`首先,因此
myFunction'\u=“result”--每隔一次输入都会得到“result”

myFunction“”xs | null$drop 1 xs=“result”--或“|[]我应该告诉您,您的
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)

我应该告诉你,你的
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)

这个怎么样?又短又甜:

{-# LANGUAGE ViewPatterns #-} 

myFunction ((<2) . length -> True) = "result"
myFunction _ = "other result"
这是无限列表的中断,但这应该不太难解决


最后,如果还启用了
LambdaCase
扩展,甚至可以编写

{-# LANGUAGE ViewPatterns, LambdaCase #-} 

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

这变得不可读且容易出错(您必须确保
\case
表达式是total!),但它确实将两种模式合并为一种模式,并且只有恒定的开销。请不要这样做:-)这个怎么样?又短又甜:

{-# LANGUAGE ViewPatterns #-} 

myFunction ((<2) . length -> True) = "result"
myFunction _ = "other result"
这是无限列表的中断,但这应该不太难解决


最后,如果还启用了
LambdaCase
扩展,甚至可以编写

{-# LANGUAGE ViewPatterns, LambdaCase #-} 

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

这变得不可读且容易出错(您必须确保
\case
表达式是total!),但它确实将两种模式合并为一种模式,并且只有恒定的开销。请不要这样做:-)

因为有多个备选解决方案,所以被接受的答案。我认为第一个解决方案是不正确的,因为
(:xs)
也匹配
[x]
。第三个解决方案可以使用.Accepted答案稍微简化,因为有多个备选解决方案。我认为第一个解决方案是不正确的,因为
(:xs)
也匹配
[x]
。第三个解决方案可以使用@williness稍微简化,并使用高效版本更新:P@WillNess更新了一个有效的版本:P