【问题标题】:Haskell filter operation with modulo带模的 Haskell 过滤器操作
【发布时间】:2017-05-11 09:48:41
【问题描述】:

我正在尝试使用 Haskell 的“过滤器”,但我遇到了困难。 我想在这样的一个函数中同时使用过滤器和模数

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

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

【问题讨论】:

    标签: haskell modulo


    【解决方案1】:

    你应该用反引号写模组

    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)
    

    但这应该谨慎使用,请仔细选择您的自定义符号,并具有清晰的可读性恕我直言。

    【讨论】:

    • 天哪,谢谢!我知道问题只是小问题,但我找不到!
    【解决方案2】:

    您必须了解的是,Haskell 有一个“非常”统一的语法(没有那么多“特殊”情况)。你调用一个函数f,参数x yf 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 确实很奇怪。但过了一段时间你开始发现这很有用,因为它节省了很多大脑周期而不考虑复杂的语法/语法规则。

    【讨论】:

      【解决方案3】:

      由于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 参数化为 nditch 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 的第一个版本。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-06
        • 1970-01-01
        • 2011-02-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多