【发布时间】:2009-11-10 23:38:09
【问题描述】:
将“map f (map g xs)”写成一个单独的 map 调用,你可以写
示例 xs = 地图 (f.g) xs
但是你如何将“filter p (filter q xs)”写成一个单独的过滤调用呢?点运算符似乎不适用于过滤器,因为它适用于地图。猜你会用别的东西做谓词吗?
【问题讨论】:
将“map f (map g xs)”写成一个单独的 map 调用,你可以写
示例 xs = 地图 (f.g) xs
但是你如何将“filter p (filter q xs)”写成一个单独的过滤调用呢?点运算符似乎不适用于过滤器,因为它适用于地图。猜你会用别的东西做谓词吗?
【问题讨论】:
如果您定义了如下所示的函数both:
both :: (a -> Bool) -> (a -> Bool) -> a -> Bool
both f g x = f x && g x
那么你可以写:
example xs = filter (both p q) xs
我不确定是否有一个标准函数可以为您执行此操作...
【讨论】:
如果您经常这样做,也可以声明自己的运算符。
infixr 3 &&:
p &&: q = \a -> p a && q a
infixr 2 ||:
p ||: q = \a -> p a || q a
not' = (.) not
all' = foldr (&&:) $ const True
any' = foldr (||:) $ const False
example xs = filter (p &&: q ||: not' r) xs
【讨论】:
为什么不是列表推导式?
example = [x | x <- xs, p x, q x]
-- for example
example = [x | x <- [1..10], (>3) x, x<5 ] -- [4]
【讨论】:
在某物上调用函数列表本质上是 Control.Monad 中的 ap 函数所做的。然后你只需and 结果。唯一有点难看的是ap 要求它的两个参数都在同一个monad 中(在本例中为List),所以我们需要将它与return 组合起来才能在这里工作。
import Control.Monad
filterByMany funcs = filter (and . ap funcs . return)
【讨论】:
我会定义一个 lambda 表达式。
module Main where
overTen :: Int -> Bool
overTen = (>10)
main :: IO ()
main = do
print $ filter (\x -> overTen x && even x) [1..20]
输出:
$ ghci Test.hs
GHCi, version 6.10.4: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main ( Test.hs, interpreted )
Ok, modules loaded: Main.
*Main> main
[12,14,16,18,20]
*Main>
【讨论】:
GHC -O2 自动执行的操作(几乎:涉及重写规则的几个不同阶段,并且通常中间阶段在之前/而不是被转回过滤器之前与其他内容相结合)
import Data.Foldable
import Data.Monoid
p = (>4)
g = (<10)
main = print $ filter (getAll . foldMap (All.) [p,g]) [1..10]
输出
[5,6,7,8,9]
仅仅因为列表是可折叠的,并且您可以将谓词结果与All monoid 结合起来
【讨论】:
类似的东西呢:
example xs = filter (forAll [p,q,r,s,t,u,v]) xs
forAll:: [(a -> Bool)] -> a -> Bool
forAll funcs x = all (map ($ x) funcs)
【讨论】:
forAll fs x = and [f x | f <- fs]。 :) 使用all 是forAll fs x = all ($ x) fs(没有map)。 :)
我会定义一个辅助函数——这可能会以更声明的方式编写,但我没有在这个系统上安装 GHCI 进行测试:
allPredicates :: [a -> Bool] -> a -> Bool
allPredicates [] _ = True
allPredicates (p:ps) x = p x && allPredicates ps x
然后
filter (allPredicates [p, q]) xs
【讨论】:
allPredicates = (. flip ($)) . flip all
allPredicates x y = all (flip ($) y) x。 GHC 解决flip 的复杂用法的效率如何?出于性能目的,我之前似乎需要删除 flip 的用法。哦,John 的allPredicates 可能性能很差,因为不能内联递归函数。哦奇怪,Data.List 对all 的定义中没有where go ...,我很确定你需要内联。