[英]How do I implement a list comprehension using map and filter?
Both map
and filter
can be implemented using list comprehension: map
和filter
都可以使用list comprehension实现:
map f xs = [f x | x <- xs]
filter p xs = [x | x <- xs, p x]
I'd like to show that the converse holds as well using the following example: 我想使用以下示例显示converse也是如此:
[expr | p <- s]
I've got so far: 我到目前为止:
map (\p -> expr) s
But this works only when pattern matching with p
succeeds on all elements of s
. 但这只适用于与
p
模式匹配在s
所有元素上成功s
。 In a way, I first want to filter s
using a pattern matching on p
. 在某种程度上,我首先想要使用
p
上的模式匹配来过滤s
。 Naturally, I tried looking into this question but I haven't been able to find a solution which didn't use list comprehension or LambdaCase. 当然,我试着调查这个问题,但我找不到一个没有使用列表理解或LambdaCase的解决方案。
But this works only when pattern matching with
p
succeeds on all elements ofs
.但这只适用于与
p
模式匹配在s
所有元素上成功s
。
Indeed: the pattern matching behaviour you describe cannot, in general, be achieved with map
and filter
alone. 实际上:您描述的模式匹配行为通常不能仅使用
map
和filter
来实现。 Expressing comprehensions in such terms only works well in the simpler case of comprehensions with a single generator and patterns that won't fail. 用这样的术语表达理解只适用于使用单个生成器和不会失败的模式的简单理解。 Rather, list comprehensions are specified in the Haskell Report in terms of
concatMap
. 相反,列表
concatMap
是根据concatMap
在Haskell报告中指定的 。 In particular, the clause about generators covers the possibility of pattern match failure: 特别是,关于生成器的条款涵盖了模式匹配失败的可能性:
--This is pseudo-Haskell; see the Report for the fine print.
[ e | p <- l, Q ] = let ok p = [ e | Q ]
ok _ = []
in concatMap ok l
The handling of match failures corresponds to what fail
does in the desugaring of list monad do-blocks. 匹配失败的处理对应于列表monad do-blocks的desugaring中的
fail
。
Yes, you cannot do pattern matching on a lambda without either using \\x -> case x of... (or LambdaCase to shorten it); 是的,你不能在没有使用\\ x - > case x of ...(或LambdaCase来缩短它)的情况下对lambda进行模式匹配; your example:
你的例子:
[2*x | (x,2) <- [(1,2), (3,4)]]
would have to be implemented as: 必须实施为:
map (\(x,_) -> 2*x) $ filter (\(_,y) -> y == 2) [(1,2), (3,4)]
Or, using LambdaCase: 或者,使用LambdaCase:
map (\(x,_) -> 2*x) $ filter (\case (_,2) -> True; _ -> False) [(1,2), (3,4)]
Also, for a point-free version: 此外,对于无点版本:
map ((2*) . fst) $ filter ((==2) . snd) [(1,2), (3,4)]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.