Haskell取模过滤操作

3

我正在尝试使用Haskell中的“filter”,但卡住了。 我想在一个函数中同时使用过滤器和取模,像这样:

multipleOf7 :: [Int] -> [Int]
multipleOf7 x = filter (test) x 
   where test = x mod 7 == 0 

我也试过使用 mod 但它不起作用。
3个回答

4

您应该使用反引号编写mod。

x `mod` 7 == 0

或正常使用它

mod x 7 == 0

在Haskell中,您可以将任何函数用作中缀运算符。如果定义了一个简单的函数,如下所示:
myFunction x y = x * y

然后,如果你想要的话,可以像这样使用它:
z = 40 `myFunction` 50

如果您希望,您也可以使用中缀样式定义函数。

x `myFunction` y = x * y

这将严格相同,您仍然可以以另一种方式称呼它:

z = myFunction 40 50 

此外,在同样的精神下,您可以轻松地在Haskell中定义自定义中缀运算符/符号。例如:
(-!!->) 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)

但是这应该谨慎使用,仔细选择自定义符号,并明确可读性的意图,以我个人的看法。

哦,太感谢了!我知道问题只是一个小问题,但我找不到它! - R.Mayer

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确实感觉有些奇怪。但是过了一段时间后,你会发现这很有用,因为它可以节省很多脑力,不需要考虑复杂的语法规则。


1

由于 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的第一版。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接