如何在 Haskell 中结合过滤器和映射

How to combine filter and mapping in Haskell

我正在用 haskell 做一些练习。我的任务是创建一个偶数平方列表,列表 [0..10].

中不包含 0

我已经在 Haskell 中使用列表理解实现了(请查看下面的代码块。)但是现在我的任务是使用函数 map 和 [=14 来实现它=].

List comprehension in Haskell:
[x^2 | x <- [0..10], mod x 2==0, x/=0]


f = (\x -> (x^2))
p = (\x -> mod x 2 == 0 && x/=0)

map1 :: (a->b) -> [a] -> [b]
map1 f [] = []
map1 f (x:xs) = f x : map1 f xs

filter1 :: (a -> Bool) -> [a] -> [a]
filter1 p [] = []
filter1 p (x:xs)
 | p x = x:filter p xs
 | otherwise = filter1 p xs

我实现了 mapfilter 函数(我知道这是多余的但它实践了我)并且我有一个平方函数。现在的问题是将 mapfilter 结合起来,我还在 p = (\x -> mod x 3 == 0 && x/=0).

处收到一条 error 消息

我的错误信息是<interactive>:4:1: error: Variable not in scope : p :: Integer -> t

这里已经有了你需要的一切。你写了

let res = [ x^2 | x <- [0..10], <b>mod x 2==0</b>, <b>x/=0</b> ]

但这意味着你也可以写

let res = [ y^2 | y <- [ x | x <- [0..10] 
                           , <b>(mod x 2==0 && x/=0)</b> ] ]
~=
let res = [ y^2 | y <- [ x | x <- [0..10], <b>test x</b> ] ]
   where
   <b>test x</b> = (mod x 2==0 && x/=0)
~=
let res = [ y^2 | y <- baz <b>[0..10]</b> ]
   where
   baz <b>xs</b> = [ x | x <- <b>xs</b>, test x ]
   test x = (mod x 2==0 && x/=0)
~=
let res = [ sqr y | y <- bar <b>test</b> [0..10] ]
   where
   sqr y = y^2
   bar <b>p</b> xs = [ x | x <- xs, <b>p</b> x ]
   test x = (mod x 2==0 && x/=0)
~=
let res = quux <b>( bar test [0..10] )</b>
   where
   quux <b>ys</b> = [ sqr y | y <- <b>ys</b> ]
   sqr y = y^2
   bar p xs = [ x | x <- xs, p x ]
   test x = (mod x 2==0 && x/=0)
~=
let res = foo <b>sqr</b> ( bar test [0..10] )
   where
   foo <b>f</b> ys = [ <b>f</b> y | y <- ys ]
   sqr y = y^2
   bar p xs = [ x | x <- xs, p x ]
   test x = (mod x 2==0 && x/=0)

所以现在我们有了两个函数,foo f ys 用于将函数 f 映射到列表 ysbar p xs 用于测试 [= 的每个元素14=] 通过谓词 p 并过滤掉所有未能通过该测试的(即所有 x 使得 p x == False)。而且,事实证明,我们已经他们的定义!

我们从原始代码中提取它们所需要做的就是抽象

let res = <b>map</b> sqr ( <b>filter</b> test [0..10] )
   where
   sqr y = y^2
   test x = (mod x 2==0 && x/=0)