Подсчет непустых списков в списках списков - PullRequest
2 голосов
/ 09 октября 2019

Я пытаюсь подсчитать количество непустых списков в списке списков с рекурсивным кодом. Моя цель - написать что-то простое, например:

prod :: Num a => [a] -> a
prod [] = 1
prod (x:xs) = x * prod xs

У меня уже есть определение и идея условия ребра:

nonEmptyCount :: [[a]] -> Int
nonEmptyCount [[]] = 0

Понятия не имею, какие советы

Ответы [ 3 ]

5 голосов
/ 09 октября 2019

Я думаю, что ваш базовый случай, может быть упрощен. В качестве базового варианта мы можем взять пустой список [], а не одноэлементный список с пустым списком. Для рекурсивного случая мы можем рассмотреть (x:xs). Здесь нам нужно провести различие между x, являющимся пустым списком, и x, являющимся непустым списком. Мы можем сделать это с помощью сопоставления с образцом или со стражами:

nonEmptyCount :: [[a]] -> Int
nonEmptyCount <b>[]</b> = 0
nonEmptyCount (x:xs) = -- &hellip;

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

nonEmptyCount :: [[a]] -> Int
nonEmptyCount = length . filter (&hellip;)

здесь вам все еще нужно заполнить &hellip;.

2 голосов
/ 09 октября 2019

Старое соответствие моде должно быть:

import Data.List

nonEmptyCount :: [[a]] -> Int
nonEmptyCount []     = 0
nonEmptyCount (x:xs) = if null x then 1 + (nonEmptyCount xs) else nonEmptyCount xs 
1 голос
/ 10 октября 2019

Следующее было размещено в комментарии, теперь удалено:

countNE = sum<$>(1<$)<<<(>>=(1`take`))

Это, безусловно, будет выглядеть пугающим для непосвященных, но на самом деле, это эквивалентно

        = sum <$> (1 <$) <<< (>>= (1 `take`))
        = sum <$> (1 <$) . (take 1 =<<)
        = sum . fmap (const 1) . concatMap (take 1)
        = sum . map (const 1) . concat . map (take 1)

что далее эквивалентно

countNE xs  =  sum . map (const 1) . concat $ map (take 1) xs
            =  sum . map (const 1) $ concat [take 1 x | x <- xs]
            =  sum . map (const 1) $ [ r | x <- xs, r <- take 1 x]
            =  sum $ [const 1 r | (y:t) <- xs, r <- take 1 (y:t)]   -- sneakiness!
            =  sum   [const 1 r | (y:_) <- xs, r <- [y]]
            =  sum   [const 1 y | (y:_) <- xs]
            =  sum   [ 1        | (_:_) <- xs]    -- replace each
                         --   non-empty list
                         --             in 
                         --                xs
               -- with 1, and
           --  sum all the 1s up!
            =  (length . (take 1 =<<)) xs
            =  (length . filter (not . null)) xs

, что должно быть намного яснее, даже если немного хитрым способом. Да, он сам по себе не рекурсивен, но и sum, и будут рекурсивно реализованы данной реализацией на Haskell.

Это переопределяет length как sum . (1 <$) и filter p xs как [x | x <- xs, p x], и использует эквивалент not (null xs) === (length xs) >= 1.

Видите? Хаскель это весело. Даже если это еще не так, но так и будет. :)

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