在Haskell的新函数中使用过滤列表

时间:2018-08-27 06:57:08

标签: list function haskell recursion composition

所以我不太确定如何正确地表达这句话,但是说我想获取列表中所有奇数的和,我是否有两个函数(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)

我还问主要是因为在使用CodeWorld输出颜色和形状时,将两个diff函数放在一起是我以前遇到的难题。

谢谢

(注意:我已经使用Haskell超过5周了,显然我是一个菜鸟)

3 个答案:

答案 0 :(得分:5)

将输出作为输入传递给(另一个)功能

您基本上想做的是使用getOddNumbers输出用作{{1}的 input }函数,因此我们可以将sumList函数定义为:

sumOddList

这里sumOddList :: [Integer] -> Integer sumOddList l = sumList (getOddNumbers l) 是我们要处理的列表,因此结果是l结果上的函数应用程序(带有getOddNumbers l函数)。

链接功能:sumList功能

上面的模式很常见:我们经常想先通过函数(.)传递数据,然后通过函数g传递结果。 Haskell具有(.) :: (b -> c) -> (a -> b) -> a -> c函数以“链接”函数。因此,我们可以将fsumList链接在一起,就像:

getOddNumbers

请注意,我们在这里不再使用sumOddList :: [Integer] -> Integer sumOddList = (.) sumList getOddNumbers 参数。 l在这里定义为“管道”,其中数据首先传递到sumOddList,然后由getOddNumbers函数进行“后处理”。

sumList函数也可以用作中缀运算符:

(.)

答案 1 :(得分:3)

以下是三种等效的编写函数Options +SymLinksIfOwnerMatch -MultiViews <IfModule mod_rewrite.c> RewriteEngine On #If your website is installed in a subfolder, change the line below to reflect the path to the subfolder. #e.g. for http://www.example.com/subdomain1/subdomain2/ make it RewriteBase /subdomain1/subdomain2 RewriteBase / #If you wish to use a custom 404 page, place a file named 404.php in your website's root and uncomment the line below. #If your website is installed in a subfolder, change the line below to reflect the path to the subfolder. #e.g. for http://www.example.com/subdomain1/subdomain2/ make it ErrorDocument 404 /subdomain1/subdomain2/404.php #ErrorDocument 404 /404.php #If your site begins with 'www', uncomment the following two lines #RewriteCond %{HTTP_HOST} !^www\. #RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L] RewriteRule ^(.*)\.htm$ $1.html [R=permanent] #DO NOT EDIT BELOW THIS RewriteRule ^index.php$ $1.html [R=301,L,QSA] RewriteCond %{REQUEST_FILENAME} -d [OR] RewriteCond %{REQUEST_FILENAME} -f RewriteRule . - [L] #slots.php RewriteRule ^slots$ "$0/" [R=301,L,QSA] RewriteRule ^slots/$ slots.php [L,QSA] RewriteRule ^slots/.*?([^\.\/]*)\.html$ slots.php?pname=$1 [L,QSA] RewriteRule ^slots/([1-2]\d{3})/(?:(0[1-9]|1[0-2])/(?:(0[1-9]|1[0-9]|2[0-9]|3[0-1])/)?)?$ slots.php?d=$1$2$3 [L,QSA] RewriteRule ^slots/[^\.]*?([^/\.]*)/$ slots.php?fname=$1 [L,QSA] RewriteRule ^slots/[^\.]*?([^/\.]*)$ "$0/" [R=301,L,QSA] #root.php RewriteRule ^root$ "$0/" [R=301,L,QSA] RewriteRule ^root/$ root.php [L,QSA] RewriteRule ^root/.*?([^\.\/]*)\.html$ root.php?pname=$1 [L,QSA] RewriteRule ^root/([1-2]\d{3})/(?:(0[1-9]|1[0-2])/(?:(0[1-9]|1[0-9]|2[0-9]|3[0-1])/)?)?$ root.php?d=$1$2$3 [L,QSA] RewriteRule ^root/[^\.]*?([^/\.]*)/$ root.php?fname=$1 [L,QSA] RewriteRule ^root/[^\.]*?([^/\.]*)$ "$0/" [R=301,L,QSA] #news.php RewriteRule ^news$ "$0/" [R=301,L,QSA] RewriteRule ^news/$ news.php [L,QSA] RewriteRule ^news/.*?([^\.\/]*)\.html$ news.php?pname=$1 [L,QSA] RewriteRule ^news/([1-2]\d{3})/(?:(0[1-9]|1[0-2])/(?:(0[1-9]|1[0-9]|2[0-9]|3[0-1])/)?)?$ news.php?d=$1$2$3 [L,QSA] RewriteRule ^news/[^\.]*?([^/\.]*)/$ news.php?fname=$1 [L,QSA] RewriteRule ^news/[^\.]*?([^/\.]*)$ "$0/" [R=301,L,QSA] #globals.php RewriteRule ^globals$ "$0/" [R=301,L,QSA] RewriteRule ^globals/$ globals.php [L,QSA] RewriteRule ^globals/.*?([^\.\/]*)\.html$ globals.php?pname=$1 [L,QSA] RewriteRule ^globals/([1-2]\d{3})/(?:(0[1-9]|1[0-2])/(?:(0[1-9]|1[0-9]|2[0-9]|3[0-1])/)?)?$ globals.php?d=$1$2$3 [L,QSA] RewriteRule ^globals/[^\.]*?([^/\.]*)/$ globals.php?fname=$1 [L,QSA] RewriteRule ^globals/[^\.]*?([^/\.]*)$ "$0/" [R=301,L,QSA] #freeplaygame.php RewriteRule ^freeplaygame$ "$0/" [R=301,L,QSA] RewriteRule ^freeplaygame/$ freeplaygame.php [L,QSA] RewriteRule ^freeplaygame/.*?([^\.\/]*)\.html$ freeplaygame.php?pname=$1 [L,QSA] RewriteRule ^freeplaygame/([1-2]\d{3})/(?:(0[1-9]|1[0-2])/(?:(0[1-9]|1[0-9]|2[0-9]|3[0-1])/)?)?$ freeplaygame.php?d=$1$2$3 [L,QSA] RewriteRule ^freeplaygame/[^\.]*?([^/\.]*)/$ freeplaygame.php?fname=$1 [L,QSA] RewriteRule ^freeplaygame/[^\.]*?([^/\.]*)$ "$0/" [R=301,L,QSA] #download.php RewriteRule ^download$ "$0/" [R=301,L,QSA] RewriteRule ^download/$ download.php [L,QSA] RewriteRule ^download/.*?([^\.\/]*)\.html$ download.php?pname=$1 [L,QSA] RewriteRule ^download/([1-2]\d{3})/(?:(0[1-9]|1[0-2])/(?:(0[1-9]|1[0-9]|2[0-9]|3[0-1])/)?)?$ download.php?d=$1$2$3 [L,QSA] RewriteRule ^download/[^\.]*?([^/\.]*)/$ download.php?fname=$1 [L,QSA] RewriteRule ^download/[^\.]*?([^/\.]*)$ "$0/" [R=301,L,QSA] #casino.php RewriteRule ^casino$ "$0/" [R=301,L,QSA] RewriteRule ^casino/$ casino.php [L,QSA] RewriteRule ^casino/.*?([^\.\/]*)\.html$ casino.php?pname=$1 [L,QSA] RewriteRule ^casino/([1-2]\d{3})/(?:(0[1-9]|1[0-2])/(?:(0[1-9]|1[0-9]|2[0-9]|3[0-1])/)?)?$ casino.php?d=$1$2$3 [L,QSA] RewriteRule ^casino/[^\.]*?([^/\.]*)/$ casino.php?fname=$1 [L,QSA] RewriteRule ^casino/[^\.]*?([^/\.]*)$ "$0/" [R=301,L,QSA] #articles.php RewriteRule ^articles$ "$0/" [R=301,L,QSA] RewriteRule ^articles/$ articles.php [L,QSA] RewriteRule ^articles/.*?([^\.\/]*)\.html$ articles.php?pname=$1 [L,QSA] RewriteRule ^articles/([1-2]\d{3})/(?:(0[1-9]|1[0-2])/(?:(0[1-9]|1[0-9]|2[0-9]|3[0-1])/)?)?$ articles.php?d=$1$2$3 [L,QSA] RewriteRule ^articles/[^\.]*?([^/\.]*)/$ articles.php?fname=$1 [L,QSA] RewriteRule ^articles/[^\.]*?([^/\.]*)$ "$0/" [R=301,L,QSA] #index.php RewriteRule ^.*?([^\.\/]*)\.html$ ?pname=$1 [L,QSA] RewriteRule ^([1-2]\d{3})/(?:(0[1-9]|1[0-2])/(?:(0[1-9]|1[0-9]|2[0-9]|3[0-1])/)?)?$ ?d=$1$2$3 [L,QSA] RewriteRule ^[^\.]*?([^/\.]*)/$ ?fname=$1 [L,QSA] RewriteRule ^\w[^\.]*?([^/\.]*)$ "$0/" [R=301,L,QSA] </IfModule> 的方法:

oddSum :: [Integer] -> Integer

顺便说一句,看看Prelude中的oddSum xs = sumList (getOddNumbers xs) oddSum xs = sumList $ getOddNumbers xs oddSum = sumList . getOddNumbers filter函数,您可以分别用它们替换sumgetOddNumbers

答案 2 :(得分:1)

  

还是有办法将这两个功能整合到一个函数中……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

之所以有用,是因为折叠是通过组成其减速器函数的变换器(如上面的mappingfiltering来变换其减速器参数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

一个foldr在做三个的工作。通过在cons操作中抽象出化简器函数,从而组成明确地实现了融合,每个这样变化的函数变成了cons转换器,因此很容易成为 >与其他类似的cons转换函数组成。