Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

As (@) pattern in Haskell

Tags:

haskell

I wrote my own take function in Haskell like this:

take' :: (Integral n, Eq a) => n -> [a] -> [a]
take' n lst
    | n <= 0 = []
    | lst == [] = []
    | otherwise = (head lst) : (take' (n-1) $ tail lst)

and it works well.

But when I try to write the same function using the as (@) pattern in function arguments, it seems that the function doesn't recognize the second guard option:

take' :: (Integral n, Eq a) => n -> [a] -> [a]
take' n lst@(hd:tl)
    | n <= 0 = []
    | lst == [] = []
    | otherwise = hd : (take' (n-1) $ tl)

When I try take' 20 [] in ghci I get the Non-exhaustive patterns in function take' error.

What am I doing wrong?

Thanks, Špela.

like image 384
Liz Avatar asked Jan 07 '23 14:01

Liz


1 Answers

Look here:

lst == [] = []

lst can never be equal to [], because you said that lst = hd:tl. Instead, you can break that branch out of the guard and into an independent pattern match to get full coverage. (You can also drop the Eq constraint once you do that.)

When you invoke take' 20 [], it tries to find a pattern that matches that, but you haven't written one: hd:tl can't match against []. And after the pattern fails to match, it won't look at the guards for that pattern.

like image 87
Ian Henry Avatar answered Jan 18 '23 09:01

Ian Henry