Использование отфильтрованного списка в новой функции в haskell - PullRequest
0 голосов
/ 27 августа 2018

Так что я не слишком уверен, как правильно сформулировать это, но скажу, что я хотел получить сумму всех нечетных чисел в списке, есть ли у меня две функции (sumList и getOddNumbers) и объединить их в sumOddList или естьспособ соединить эти два в одну функцию?Если нет лучшей функции, как именно я бы объединил их в sumOddList?

getOddNumbers :: [Integer] -> [Integer]
getOddNumbers [] = []
getOddNumbers (x:xs)
    |odd x = x:getOddNumbers xs
    |otherwise = getOddNumbers xs

sumList :: [Integer] -> Integer
sumList list = case list of
   [] -> 0
   (x:xs) -> x + (sumList xs)

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

Спасибо

(Примечание: я использую Haskell уже более 5 недель, и я совершенно нуб))

Ответы [ 3 ]

0 голосов
/ 27 августа 2018

Передача выходных данных в качестве входных данных для (другой) функции

Хорошо, что вы в основном хотите сделать, это использовать выход из getOddNumbers как введите для функции sumList, поэтому мы можем определить функцию sumOddList как:

sumOddList :: [Integer] -> Integer
sumOddList l = sumList (getOddNumbers l)

Здесь l - это список, который мы хотим обработать, и результат, таким образом, является функциейприменение к результату getOddNumbers lsumList функцией).

Функции цепочки: (.) функция

Вышеприведенный шаблон довольно распространен: часто мы хотим передавать данныесначала через функцию g, а результат через функцию f.Haskell имеет функцию (.) :: (b -> c) -> (a -> b) -> a -> c для «цепочки» функций.Таким образом, мы можем связать sumList и getOddNumbers вместе как:

sumOddList :: [Integer] -> Integer
sumOddList = (.) sumList getOddNumbers

Обратите внимание, что мы больше не используем параметр l здесь.sumOddList здесь определяется как «конвейер», в котором данные сначала передаются в getOddNumbers, а затем «пост-обрабатываются» функцией sumList.

Функция (.) также можетиспользоваться в качестве инфиксного оператора:

sumOddList :: [Integer] -> Integer
sumOddList = sumList . getOddNumbers
0 голосов
/ 27 августа 2018

или есть способ объединить эти две функции в одну функцию ... sumOddList?

Да, есть.

Цепочка функций с помощьюодин вывод как другой работает, особенно при ленивой оценке, но оставляет нас зависимыми от fusion , который должен выполнять компилятор.Что, в конце концов, не гарантируется (и часто не происходит).

Вместо этого то, что вы сказали :

mapping f cons x xs = cons (f x) xs

filtering p cons x xs = if (p x) then (cons x xs) else xs

transduce xf cons z xs = foldr (xf cons) z xs

sumOddList xs = transduce (filtering odd) (+) 0 xs

Таким образом,

> sumOddList [1..10]
25
> sum [1,3..10]
25
> transduce (mapping (+1) . filtering odd) (+) 0 [1..10]
35
> sum . filter odd . map (+1) $ [1..10]
35
> sum . map (+1) . filter odd $ [1..10]
30
> transduce (filtering odd . mapping (+1)) (+) 0 [1..10]
30

Это работает, потому что складывает предохранитель путем составления преобразователей их функций-редукторов (например, mapping и filtering выше, которые преобразуют их аргумент редуктора cons):

foldr (+) 0
   . foldr (\x r -> x+1 : r) []
       . foldr (\x r -> if odd x then x : r else r) [] 
         $ [1..10]
=
foldr (+) 0
   . foldr ((\cons x r -> cons (x+1) r) (:)) []
       . foldr ((\cons x r -> if odd x then cons x r else r) (:)) [] 
         $ [1..10]
=
     foldr ((\cons x r -> cons (x+1) r) (+)) 0
       . foldr ((\cons x r -> if odd x then cons x r else r) (:)) [] 
         $ [1..10]
=
         foldr ((\cons x r -> if odd x then cons x r else r) 
                  ((\cons x r -> cons (x+1) r)   (+))) 0 
         $ [1..10]
=
         foldr ( ( (\cons x r -> if odd x then cons x r else r) 
                 . (\cons x r -> cons (x+1) r) ) (+))  0 
         $ [1..10]
=
         foldr ( (filtering odd . mapping (+1))  (+))  0 
         $ [1..10]
=
         foldr (  filtering odd ( mapping (+1)   (+))) 0 
         $ [1..10]
=
         30

One foldr делает работу трех.Fusion явно достигается путем составления функций редуктора после абстрагирования от них операции cons, каждая такая измененная функция становится преобразователем cons, таким образом, она может составлять , составленную с другими такими cons -преобразующими функциями.

0 голосов
/ 27 августа 2018

Ниже приведены три эквивалентных способа написания функции oddSum :: [Integer] -> Integer:

oddSum xs = sumList (getOddNumbers xs)

oddSum xs = sumList $ getOddNumbers xs

oddSum = sumList . getOddNumbers

Кстати, взгляните на функции filter и sum в Prelude которым можно заменить getOddNumbers и sumList соответственно.

...