使用模数的Haskell过滤器操作

时间:2017-05-11 09:48:42

标签: haskell modulo

我正在尝试使用Haskell的“过滤器”,但我已经卡住了。 我想在这样的一个函数中使用过滤器和模数

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

我也尝试使用mod,但它不起作用。

3 个答案:

答案 0 :(得分:3)

你应该使用反引号

编写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)

但是这应该谨慎使用,仔细选择你的自定义符号,并且具有明确的可读性恕我直言。

答案 1 :(得分:2)

你必须要了解的是Haskell有一个“非常”统一的语法(没有那么多“特殊”的情况)。您使用带有f的参数x y调用函数f x y。现在mod只是一个普通的函数,就像所有其他函数一样。所以你应该用:

来调用它
mod x 7

你也可以使用backtics来调用二元运算符,其函数介于两者之间:

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 x = mod x 7 == 0

您还可以重写test功能:

test = (0 ==) . flip mod 7

或制作更短的过滤器,如:

multipleOf7 :: Integral b => [b] -> [b]
multipleOf7 = filter ((0 ==) . flip mod 7)

(意见)我个人认为,首先看mod x 7确实很奇怪。但过了一段时间,你开始觉得这很有用,因为它可以节省大量的脑循环而不考虑复杂的语法/语法规则。

答案 2 :(得分: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一样,我可能loosen the Int into an Integral a => a,因为库函数mod :: Integral a => a -> a -> a就像一般。我还将 7 参数化为 n ditch the 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)

Pointfree风格有时更具可读性。我认为这不是这种情况。这里有另一种变体,

multipleOf :: Integral a => a -> [a] -> [a]
multipleOf n = filter ((== 0) . (`mod` n))

不过,我喜欢第一个版本where或lambda更好。