函数noThirds中的非穷举模式

时间:2014-04-20 04:29:43

标签: haskell

所以,我的问题是,我必须编写一个程序来过滤列表中的所有3 * x(3,6,9 ...)元素。我的程序看起来像:

length'  :: [a] -> Int
length' = foldr (\_ -> (+1)) 0

help_ :: [a] -> [a] -> [a]
help_ (x:xs) [] = help_ (xs) [x]
help_ [] (x) = (x)
help_ (x:xs) (y)
    |((length' [xs]) ==0) = (y)
    |((length' [y]) `mod` 2 ==0) = help_ (xs) (y)
    |otherwise = help_ (xs) (y++[x])

noThirds :: [a] -> [a]
noThirds [x] = help_ [x] []

编译器接受此但在我输入时会出现错误“函数noThirds中的非穷举模式” “noThirds [1,2,3,4,5,6,7,8]” 。我想这是因为我错过了各种各样的“帮助......”但是我没有得到它。我很感激每一个帮助! 不允许使用Btw预定义列表和算术函数。

3 个答案:

答案 0 :(得分:2)

jozefg已经回答了你的问题。我还要指出更多的事情。

小心!表达式

((length' [xs]) ==0)
((length' [y]) `mod` 2 ==0)

评估为

(1 ==0)
(1 `mod` 2 ==0)

所以他们都是假的。你想要

((length' xs) ==0)
((length' y) `mod` 2 ==0)

此外,在这些功能中,计算长度通常会导致性能低下,并且被认为是不好的风格。考虑以这种方式预处理您的列表

addPosition :: [a] -> [(Int,a)]
addPosition xs = go 0 xs
    where go n []     = ...
          go n (y:ys) = ...
-- Example: addPosition [33,66,20] ===> [(0,33),(1,66),(2,20)]
-- This is equivalent to (zip [0..]) but we can not use list functions.

然后,添加一些后处理来过滤想要的元素:现在这更容易,因为每个元素都被其位置标记。

答案 1 :(得分:1)

这是因为noThirds只有一个模式,[x]只与单个元素列表匹配。 [x]完全等同于(x : [])。我认为你的意思是

noThirds :: [a] -> [a]
noThirda xs = help_ xs []

答案 2 :(得分:0)

列表的结构是:

  • 空列表[]
  • 或后跟列表其余部分的元素(x:xs)

使用列表的结构来定义结果(使用保护表达式):

noThirds :: [Int] -> [Int]

noThirds [] = []
noThirds (x:xs)
  | x `mod` 3 == 0 = rest
  | otherwise      = x : rest
    where
      rest = noThirds xs

该功能现在过滤掉所有可被3整除的元素。

你可能希望过滤掉一个可被3整除的索引的所有元素。为此,引入一个辅助函数,它传递你当前所在的索引并改为使用索引上的guard:

noThirds :: [Int] -> [Int]
noThirds xs = noThirds' xs 1

noThirds' :: [Int] -> Int -> [Int]
noThirds' [] _ = []
noThirds' (x:xs) i
  | i `mod` 3 == 0 = rest
  | otherwise      = x : rest
    where
      rest = noThirds' xs (succ i)

现在您不需要计算列表的长度。

关于H-99的解决方案16的更多答案:九十九个Haskell问题: http://www.haskell.org/haskellwiki/99_questions/Solutions/16