Использование foldl для подсчета количества истинных значений - PullRequest
5 голосов
/ 22 февраля 2009

Я пытаюсь найти способ выполнить следующую функцию с помощью foldl:

count a = length (filter (\i -> i) a)

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

count = foldl (\i -> 
            case i of
                True -> (1+)
                False -> (0+)
            ) 0

Который даже не компилировался. Есть предложения?

Ответы [ 2 ]

9 голосов
/ 22 февраля 2009

Итак, давайте проверим типы задействованных функций

Prelude> :t (\i -> case i of { True -> (1+) ; False -> (0+) })
(\i -> case i of { True -> (1+) ; False -> (0+) }) :: (Num t) => Bool -> t -> t
Prelude> :t foldl
foldl :: (a -> b -> a) -> a -> [b] -> a

Итак, для вашего списка Bool s, b - это Bool, но используемая функция имеет Bool в качестве первого аргумента, а не второго. Накопленная стоимость является первым аргументом. Так что вместо этого вы можете сделать

foldl (\acc p -> case p of { True -> acc + 1 ; False -> acc }) 0

Или, если вы хотите просто исправить порядок аргументов, используйте исходную функцию с flip

Prelude> :t flip
flip :: (a -> b -> c) -> b -> a -> c

foldl (flip (\i -> case i of
                           True -> (1+)
                           False -> (0+)
             )) 0

Или вы можете быть более кратким: foldl (flip ((+) . fromEnum)) 0

4 голосов
/ 22 февраля 2009

Как насчет:

count = foldl (\i v -> if v then i + 1 else i) 0

Еще один способ сделать это без foldl:

count list = sum $ map fromEnum list

Благодарим Логана за указание fromEnum. Не слышал об этом раньше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...