[Haskell-beginners] Pattern matching with one, two or more arguments

Brent Yorgey byorgey at seas.upenn.edu
Sun Nov 29 13:13:31 EST 2009


On Sun, Nov 29, 2009 at 06:41:22PM +0100, legajid wrote:
> Hello,
> I'm writing a little word game that consists of the following : between a 
> consonant and a vowel, insert "AV" so "fabien" becomes "fAVabAVien".
>
> When i type : f "fabine", the result is ok ("fAVabAVinAVe")
> When i type : f "fabien", the result is fAVabAVie *** exception :prelude 
> empty list
>
> Here's my program
>
> voyelles="aeiouy"
> consonnes="bcdfghjklmnpqrstvwxz"
>
> est_voyelle x = x `elem` voyelles
> est_consonne x = x `elem` consonnes
>
> --f []=[] ; unuseful - conflict with f a = a
>
>
> -- detect a vowel following a consonant
> trait a b = est_consonne a && est_voyelle b
>
>
>
> f (a:b) is never invoked (i wrote EP instead of AV to trace the problem). 
> f(a:b:c) seems to always take precedence over the other patterns.
> I expect f(a:b:c) to treat words greater than or equal to 3 letters, f(a:b) 
> the last two letters of the word (no third part) and f a the last letter.

This is not correct.  The patern (a:b:c) matches words greater than or
equal to TWO letters, not three.  In the case of a two-letter word, c
is the empty list.  For example, the word "in" is ('i':'n':[]).

> f (a:b:c) =
>    case trait a b of
>        True -> a : (" AV " ++ f (b:c))
>        False -> a : f (b:c)
> f (a:b) =
>    case trait a (head b) of
>        True -> a : (" EP " ++ f ( b) )
>        False -> a : f ( b)
> f a =  a

The problem is with the call to 'head b' -- when f is called on a
one-letter word, it matches the pattern (a:b) with b the empty list,
and the call to 'head' crashes.  You do not need to check the trait in
this case at all.  In fact, you do not need this entire case at all!
Just the first case and the third should suffice.

-Brent


More information about the Beginners mailing list