How a Haskell filter works with a module

I'm trying to use a "filter" from Haskell, but I'm stuck. I want to use filter and module together in one function like this

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

      

I also tried to use mod

but it doesn't work.

+3


source to share


3 answers


You must write a written mod using backquote

x `mod` 7 == 0

      

or use it normally

mod x 7 == 0

      

In haskell, you can use any function like infix. If you define a simple function like

myFunction x y = x * y

      

then if you want you can use it like:

z = 40 `myFunction` 50

      

if you like, you can also define a function with infix type.

x `myFunction` y = x * y

      



it will be strictly the same, and you can still call it in a different way:

z = myFunction 40 50 

      


Also, along the same lines, you can easily define custom infix operators / symbols in Haskell. For example:

(-!!->) a b = (a,b)
-- or identically, but no need for backticks for infix operators
a -!!-> b = (a,b)

      

which can be used like this:

c = 1 -!!-> 2
-- and now c == (1,2)

      

but this should be used sparingly, choose your custom character carefully and with a clear intention of readability IMHO.

+3


source


What you should understand is that Haskell has a "very" uniform syntax (there aren't many "special" cases). You call a function f

with arguments x y

using f x y

. Now mod

it's just a regular function like all other functions. Therefore, you should call him:

mod x 7

      

You can also use callbacks to call a binary operator with a function in between such as:

x `mod` 7

      

So, you can fix the problem with

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

or cleaner:



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

You can also rewrite the function test

so that:

test = (0 ==) . flip mod 7

      

or make a shorter filter like:

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

      

(opinion) In my personal opinion, it is really strange to see at first mod x 7

. But after a while, you will start to find it useful, as it saves a lot of brain cycles by not taking into account complex syntax / grammar rules.

+2


source


Since filter :: (a -> Bool) -> [a] -> [a]

in your case a = Int,

multipleOf7 :: [Int] -> [Int]
multipleOf7 ns = filter f ns
  where
    f :: Int -> Bool
    f i = i `mod` 7 == 0

      

Similar to Willem Van Onsem, I will probably decouple Int in the integral a => a , since it is a library function mod :: Integral a => a -> a -> a

as it is in general. I would also parameterize 7 to n, cut ns, and write f as a lambda:

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

      

Then Willem Van Onsem rewrites it into a dotless style :

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

      

Pointfree style is sometimes more readable. I would say that it is not. Another option is also available here,

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

      

However, I like the first versions with where

or lambda better.

+1


source







All Articles