Erakura
Erakura

Reputation: 35

Pattern match(es) are non-exhaustive

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?

Upvotes: 3

Views: 8088

Answers (2)

Benjamin Hodgson
Benjamin Hodgson

Reputation: 44614

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)

Upvotes: 7

Antisthenes
Antisthenes

Reputation: 420

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.

Upvotes: 4

Related Questions