Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ?

like image 555
Stephane Rolland Avatar asked Aug 25 '14 20:08

Stephane Rolland


2 Answers

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
like image 58
Sibi Avatar answered Nov 03 '22 04:11

Sibi


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 
like image 22
Stephane Rolland Avatar answered Nov 03 '22 02:11

Stephane Rolland