Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly use guards in Haskell?

I'm new to Haskell and I'm trying to write simple functions to get myself used to the syntax, I want to write my own function for adding a certain element to a list at a specific index. Here's what I wrote in Atom (my text editor):

addElem :: a->[a]->Int->[a]
addElem elem list index
 | index <= 0            = elem:list
 | index < (length list) = a ++ (elem:b) where a = take index list; b = drop index list
 | otherwise             = list

The idea is that it won't freak out as long as index is an Int and elem is of the same type as the elements of list, but when I try to load this into ghci I get "parse error on `|'." Do I need to constrain the types of the arguments? I'm reading Learn You A Haskell but I haven't gotten to the part where they fully explain how the indentations work, so my error might also be there.

like image 277
Eben Kadile Avatar asked Dec 19 '22 09:12

Eben Kadile


1 Answers

where blocks need to occur at the end of the whole function, and are shared amongst all the cases. You probably meant to use a let:

addElem :: a -> [a] -> Int -> [a]
addElem elem list index
 | index <= 0            = elem:list
 | index < (length list) = let a = take index list; b = drop index list in a ++ (elem:b)
 | otherwise             = list

Also, note that let could be written more concisely as let (a,b) = splitAt index list in .... splitAt is also in the Prelude. Of course, you could also just move the where block to the end of the function (Haskell's laziness makes this easy to reason about).

addElem :: a -> [a] -> Int -> [a]
addElem elem list index
 | index <= 0            = elem:list
 | index < (length list) = a ++ (elem:b)
 | otherwise             = list
 where
   a = take index list
   b = drop index list

Personally, I like this less because it suggests that a and b may be used elsewhere in the function.

Section 4.4.3 of the 2010 Haskell Report goes into more detail on where where is allowed.

like image 62
Alec Avatar answered Jan 05 '23 11:01

Alec