2015-01-16 4 views
2

Мне нужна функция, которая проверяет условие в списке.Проверка состояния в Haskell

Например:

countP :: [a] -> (a -> Bool) -> Int 

с входом:

countP [1,-2,0,-1,5] (>0) 

должен возвращать 2, потому что есть два числа больше нуля.

Вот что я сделал до сих пор:

countP :: [a] -> (a -> Bool) -> Int 
countP [] _ = [] 
countP (x:xs) condition = if condition x then 1:countP xs condition else countP xs condition 

Это возвращение [1,1] вместо числа два. Он должен быть рекурсивным.

Как я могу это сделать?

+4

Вы настаиваете на том, чтобы делать это вручную? Поскольку вы можете использовать [фильтр] (http://hackage.haskell.org/package/base-4.7.0.2/docs/Prelude.html#v:filter) и [длина] (http://hackage.haskell.org /package/base-4.7.0.2/docs/Prelude.html#v:length). – zegkljan

ответ

2

Вы должны добавить результат, как этот

countP :: [a] -> (a -> Bool) -> Int 
countP [] _ = 0 
countP (x:xs) condition = (if condition x then 1 else 0) + (countP xs condition) 

Всякий раз, когда condition x истинно, мы используем 1 иначе 0 и мы рекурсивный вызов countP и добавить их.

Итак, когда вы вызываете его как этот

countP [1, -2, 0, -1, 5] (>0) 

будет оцениваться рекурсивно, как этот

(if (> 0) 1 then 1 else 0) + (countP [-2, 0, -1, 5] (> 0)) 
1 + (countP [-2, 0, -1, 5] (> 0)) 
1 + (if (> 0) -1 then 1 else 0) + (countP [0, -1, 5] (> 0)) 
1 + 0 + (countP [0, -1, 5] (> 0)) 
1 + 0 + 0 + (countP [-1, 5] (> 0)) 
1 + 0 + 0 + 0 + (countP [5] (> 0)) 
1 + 0 + 0 + 0 + 1 + (countP [] (> 0)) 
1 + 0 + 0 + 0 + 1 + 0 = 2 

(countP [] (> 0)) оценивается как 0 из-за нашей базовое условие из наша рекурсивная функция countP [] _ = 0. Это означает, что независимо от второго параметра, если первый параметр является пустым списком, тогда возвратите 0.

2

Вы, кажется, слишком думали об этом. Вы можете использовать некоторые из Prelude при условии, функции и компоновать их для получения результата:

length $ filter (>0) [1,-2,0,-1,5] 

length примет список и сказать вам, как долго. filter берет предикат и сообщает вам, сколько элементов в предоставленном списке соответствуют этому предикату. Итак, если вы получили length из filter ed ed, вы настроены.

countP xs f = length $ filter f xs 
1

Существует функция специально для подсчета количества вещей в списке, и это называется length. Вы могли бы сделать что-то вроде

countP' [] _ = [] 
countP' (x:xs) condition = if condition x then 1 : countP' xs condition else countP' xs condition 

countP xs condition = length (countP' xs condition) 

Однако, это требует двух функций и делает дополнительную работу. Вместо того, чтобы вы могли работать непосредственно с Int с вместо [Int] с:

countP :: [a] -> (a -> Bool) -> Int 
countP [] _ = 0 
countP (x:xs) condition = ... 

Я до сих пор позволяют заполнить пробелы здесь, знайте, что вы не очень далеко от правильного решения с тем, что у вас уже есть.

Однако, если бы я собирался реализовать этот код в проекте, я бы просто тянуться length и filter:

countP xs condition = length (filter condition xs) 

Это то, что я бы назвал идиоматическое определение (до того аргумента).

Смежные вопросы