这是我正在考虑的一个示例问题:取每个x从1到n的总和,其中x可以被3或5整除,所以像这样:
divisible a b = rem b a == 0
sum3or5 n = sum [x | x <- [1..n], divisible 3 x || divisible 5 x]
Run Code Online (Sandbox Code Playgroud)
来自Scheme,我想使用过滤器实现这一点,如下所示:
divisible a b = rem b a == 0
sum3or5 n = sum $ filter div3or5 [1..n] where
div3or5 n = (divides 3 n) || (divides 5 n)
Run Code Online (Sandbox Code Playgroud)
我在想,是否有一个更高阶的逻辑OR(||),所以我可以写'div3or5'无点样式,这样的东西?:
divisible a b = rem a b == 0
sum3or5 = sum $ filter (divisible 3 || divisible 5) . range
Run Code Online (Sandbox Code Playgroud)
谢谢您的帮助.
kqr*_*kqr 11
是.你可以(||)从布尔语"升级" 到功能,从某些东西到布尔.所以你想要类似的东西
(||) :: Bool -> Bool -> Bool
Run Code Online (Sandbox Code Playgroud)
变成
(||) :: (r -> Bool) -> (r -> Bool) -> (r -> Bool)
Run Code Online (Sandbox Code Playgroud)
这恰好是函数的应用实例的好处.
liftA2 :: (a -> b -> c) -> (r -> a) -> (r -> b) -> (r -> c)
Run Code Online (Sandbox Code Playgroud)
所以
liftA2 (||) :: (r -> Bool) -> (r -> Bool) -> (r -> Bool)
Run Code Online (Sandbox Code Playgroud)
这意味着,在您的情况下,您可以将过滤器编写为
filter (liftA2 (||) (divides 3) (divides 5))
Run Code Online (Sandbox Code Playgroud)
它取一个整数并决定它是否可以被3或5整除.
如果你愿意,你可以定义类似的东西
(<||>) = liftA2 (||)
Run Code Online (Sandbox Code Playgroud)
或者,等效地,
f <||> g = \x -> f x || g x
Run Code Online (Sandbox Code Playgroud)
然后你可以把你的过滤器写成
filter (divisible 3 <||> divisible 5)
Run Code Online (Sandbox Code Playgroud)
在操作符周围包装尖括号是一种习惯用法,表示它们被提升为其他东西(仿函数,应用程序,幺半群).