Haskell-由于我不明白的原因而出现的非穷举模式

时间:2019-12-15 20:29:53

标签: haskell design-patterns functional-programming matching

因此,我正在尝试编写一个函数,该函数给定两个整数列表,将每个列表的第i个偶数相加,然后将它们返回到另一个列表中。如果列表中的一个没有第i个偶数,则考虑为0。例如,如果列表是[1,2,1,4,6]和[2,2],则返回[4,6,6]([2 + 2,4 + 2,6 + 0])。我有以下代码:

addEven :: [Int] -> [Int] -> [Int] 
addEeven [] [] = []
addEeven (x:xs) [] = filter (\g -> g `mod`2 == 0) (x:xs)
addEven [] (y:ys) = filter (\g -> g `mod` 2 == 0) (y:ys)
addEven (x:xs) (y:ys) = (a + b):(addEven as bs)
                        where 
                          (a:as) = filter (\g -> g `mod` 2 == 0) (x:xs)
                          (b:bs) = filter (\g -> g `mod` 2 == 0) (y:ys)

在上一个示例中运行该命令时,我得到:

[4,6*** Exception: ex.hs:(4,1)-(8,101): Non-exhaustive patterns in function addEven

我真的看不到我所缺少的内容,因为它不能与我输入的任何内容一起使用。

2 个答案:

答案 0 :(得分:1)

filter可能会消除元素,因此filter (\g -> g mod 2 == 0)不能返回任何元素,因此模式(a:as)(b:bs)可能会失败

话虽这么说,我认为您在这里使问题变得太复杂了。您可以首先定义一个辅助函数,以添加列表的两个元素:

addList :: Num a => [a] -> [a] -> [a]
addList (x:xs) (y:ys) = (x+y) : addList xs ys
addList xs [] = xs
addList [] ys = ys

然后,我们对两个参数进行过滤,并制作一个类似于以下内容的函数addEven

addEven :: Integral a => [a] -> [a] -> [a]
addEven xs ys = addList (filter even xs) (filter even ys)

或使用on :: (b -> b -> c) -> (a -> b) -> a -> a -> c

import Data.Function(on)

addEven :: Integral a => [a] -> [a] -> [a]
addEven = addList `on` filter even

答案 1 :(得分:0)

虽然在这种情况下使用filter是非常本能的,但也许两次使用filter然后对结果进行汇总对于大型列表可能效率不高。为什么我们不立即做所有工作以进行更改。?

addMatches :: [Int] -> [Int] -> [Int]
addMatches [] [] = []
addMatches [] ys = filter even ys
addMatches xs [] = filter even xs
addMatches xs ys = first [] xs ys
                   where
                   first :: [Int] -> [Int] -> [Int] -> [Int]
                   first rs [] ys     = rs ++ filter even ys
                   first rs (x:xs) ys = rs ++ if even x then second [x] xs ys
                                                        else first [] xs ys
                   second :: [Int] -> [Int] -> [Int] -> [Int]
                   second [r] xs []     = [r] ++ filter even xs
                   second [r] xs (y:ys) = if even y then first [r+y] xs ys
                                                    else second [r] xs ys

λ> addMatches [1,2,1,4,6] [2,2]
[4,6,6]