Stephane Rolland
Stephane Rolland

Reputation: 39906

Pattern-Matching mixed with guards

I wanted to define the function:

accumulate_list' :: Num a => [a] -> ( a -> a -> a ) -> a
accumulate_list' l f 
    | [] f = 0
    | (x:xs) f = f x (accumulate_list xs f)

but it doesn't compile, complaining that x, xs, x, xs, are Not in scope.

Trying to achieve the same result, I have defined this function

accumulate_list :: Num a => [a] -> ( a -> a -> a ) -> a
accumulate_list [] f = 0
accumulate_list (x:xs) f = f x $ accumulate_list xs f

it compiles well, and does like sum does on a list if the functgion passed in parameter is (+). Yes, I finally found that indeed what I wanted to achieve was already existing in Prelude as the sum function.

However, I don't understand why the first version with mixed guards and pattern matching doesn't compile. What is the problem ?

Upvotes: 10

Views: 8941

Answers (2)

Sibi
Sibi

Reputation: 48654

It is because guards are basically a boolean expression. They have to evaluate to either True or False. Something like this should typecheck:

accumulate_list' :: (Eq a, Num a) => [a] -> ( a -> a -> a ) -> a
accumulate_list' l f 
    | l == [] = 0
    | otherwise = undefined -- fill out undefined

It's also worth mentioning that since pattern guards were added to Haskell 2010, you're allowed to mix patterns and guards like so:

accumulate_list' :: (Eq a, Num a) => [a] -> ( a -> a -> a ) -> a
accumulate_list' l f
    | []     <- l = 0          --pattern for the empty list case
    | 10 < 5      = 10         --arbitrary regular guard just because 
    | (x:xs) <- l = undefined  --pattern for the non-empty case

Upvotes: 26

Stephane Rolland
Stephane Rolland

Reputation: 39906

Using what @Sibi's answer provided, I've completed it so as to provide entire working code example:

accumulate_list' :: (Eq a ,Num a) => [a] -> ( a -> a -> a ) -> a
accumulate_list' l f 
    | l == [] = 0
    | otherwise = f x $ accumulate_list xs f
                    where (x:xs) = l 

Upvotes: 4

Related Questions