3

I'm trying to create a function that eliminates multiples of a given Integer from a list of Integers, in the form multiples x [y], where x is the given Integer, and y is the list.

Here's what I have:

multiples :: Integer -> [Integer] -> [Integer]
multiples a [] = []
multiples a [b] = filter (\l -> l `mod` a /= 0) [b]

multiples will fail when called, saying "Non-exhaustive patterns in function multiples". So I used ghci -Wall with my file to see what patterns were missing, and it returns this:

multiples.hs:2:1: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for `multiples': Patterns not matched: _ (_:_:_)

multiples.hs:2:11: warning: [-Wunused-matches]
    Defined but not used: `a'

I get the feeling I'm missing something really simple with line 2, but I'm a bit stuck. What am I doing wrong?

Will Ness
  • 70,110
  • 9
  • 98
  • 181
Erakura
  • 35
  • 1
  • 5

2 Answers2

7

Welcome to Stack Overflow! There are a couple of things to fix in your function, but I'll start with the one you seem the most confused about: here [b] is a pattern matching a one-element list, naming its single item b. ([b, c] would be a pattern matching a two-element list, etc.) It's not a pattern matching an arbitrarily long list of bs. GHC is telling you off because you haven't accounted for the case where the function has been given a two-or-more-element list.

If you want to match an arbitrary list of bs, omit the square brackets. Additionally, the first line of your function is not necessary because the second line already deals with that case.

multiples :: Integer -> [Integer] -> [Integer]
multiples a bs = filter (\b -> b `mod` a /= 0) bs

Or, using a list comprehension,

multiples :: Integer -> [Integer] -> [Integer]
multiples a bs = [b | b <- bs, b `mod` a /= 0]

Two more things: I'd name this function withoutMultiples because it filters out multiples of a, and because Haskell functions are curried by default you can omit the bs in the filter version.

withoutMultiples :: Integer -> [Integer] -> [Integer]
withoutMultiples a = filter (\b -> b `mod` a /= 0)
Benjamin Hodgson
  • 42,952
  • 15
  • 108
  • 157
  • Thank you for the help - I missed the `=` when copying my code over here. Changing both instances of `[b]` to `bs` fixed the issue! – Erakura Sep 17 '16 at 23:51
4

Your pattern

    multiples a [b]

expects an Integer (bound to name "a") and list of Integer containing one element (bound to name "b"). Remove square brackets (which will change type of "b" to [Integer]) in this pattern and it should be working. Also you can curry this function to form

    multiples a = filter (\l -> l `mod` a /= 0)

and omit first pattern as it should be covered by filter function.

Antisthenes
  • 420
  • 2
  • 8
  • Thank you for the answer - I missed that `[b]` would imply a one element list. Replacing it with `bs` indeed fixed the issue. The first pattern was added as a result of troubleshooting the non-exhaustive pattern error. – Erakura Sep 17 '16 at 23:53
  • Fun fact - it is possible to write that function in point-free style, which looks like this `multiples = filter . ((/=) 0 .) . flip mod` Sometimes it's good exercise to look at that and try to understand all the transformations. – Antisthenes Sep 18 '16 at 00:21