我正在尝试使用Haskell中的“filter”,但卡住了。 我想在一个函数中同时使用过滤器和取模,像这样:
multipleOf7 :: [Int] -> [Int]
multipleOf7 x = filter (test) x
where test = x mod 7 == 0
我也试过使用
mod
但它不起作用。您应该使用反引号编写mod。
x `mod` 7 == 0
或正常使用它
mod x 7 == 0
myFunction x y = x * y
z = 40 `myFunction` 50
如果您希望,您也可以使用中缀样式定义函数。
x `myFunction` y = x * y
这将严格相同,您仍然可以以另一种方式称呼它:
z = myFunction 40 50
(-!!->) a b = (a,b)
-- or identically, but no need for backticks for infix operators
a -!!-> b = (a,b)
c = 1 -!!-> 2
-- and now c == (1,2)
需要了解的是,Haskell有一个非常统一的语法(没有太多特殊情况)。你可以使用 f x y
的形式调用带有参数 x y
的函数 f
。现在,mod
只是像其他所有函数一样的普通函数。因此,你应该这样调用它:
mod x 7
您还可以使用反引号将函数放在两个操作数之间以调用二进制运算符,例如:
x `mod` 7
所以你可以通过以下方法解决问题:
multipleOf7 :: [Int] -> [Int]
multipleOf7 x = filter (test) x
where test x = mod x 7 == 0
multipleOf7 :: [Int] -> [Int]
multipleOf7 = filter test
where test <b>x</b> = <b>mod x 7</b> == 0
test
函数,使其如下所示:test = (0 ==) . flip mod 7
multipleOf7 :: Integral b => [b] -> [b]
multipleOf7 = filter ((0 ==) . flip mod 7)
(个人观点) 以我的个人看法,一开始看到mod x 7
确实感觉有些奇怪。但是过了一段时间后,你会发现这很有用,因为它可以节省很多脑力,不需要考虑复杂的语法规则。
由于 filter :: (a -> Bool) -> [a] -> [a]
,在您的情况下 a = Int,
multipleOf7 :: [Int] -> [Int]
multipleOf7 ns = filter f ns
where
f :: Int -> Bool
f i = i `mod` 7 == 0
像Willem Van Onsem一样,我可能会将 Int 放松为 Integral a => a ,因为库函数mod :: Integral a => a -> a -> a
同样通用。我还会将 7 参数化为 n ,放弃 ns 并将 f 写成lambda表达式:
multipleOf :: Integral a => a -> [a] -> [a]
multipleOf n = filter (\i -> i `mod` n == 0)
然后Willem Van Onsem将其改写为pointfree style:
multipleOf7 :: Integral a => [a] -> [a]
multipleOf7 = filter ((0 ==) . flip mod 7)
multipleOf :: Integral a => a -> [a] -> [a]
multipleOf n = filter ((== 0) . (`mod` n))
不过,我更喜欢带有where
或lambda的第一版。