A couple of notes:
First note that you want get 1
to return the first element in your list, that's not the common choice in many languages including Haskell ([2, 3, 5] !! 1 = 3
).
Second, although elementAt
is a recursive function over lists, it can be defined more efficiently in the old fashion recursive way. fold
functions are not good choices here, because fold
goes through every element of the list. But we want elementAt
recursion to stop the moment that we find the element.
Given this, here is how you can implement elementAt
recursively:
elementAt :: Int -> [a] -> a
elementAt i (x:xs) = if i == 1 then x else elementAt (i-1) xs
And here's the implementation using foldl
:
elementAt' :: Int -> [a] -> a
elementAt' i (x:xs) =
snd $
foldl
(\(j, a) b ->
if j < 1 then (j-1, a) else (j-1, b))
(i-1, x)
xs
The seed value of foldl
is a tuple: (i-1, x)
where x
is the head of the list.
Note that the return result of fold
functions must be of the same type of their seed. Hence here foldl
returns a tuple: (j-1, a)
where a
is the final result, if the index is found; otherwise (j-1, b)
where b
is the current element of the list.
You can see how foldl
goes through every element of the list even after it found the element at index that we were looking for (it keeps returning the previous result a
that will be the final result).
PS. These elementAt
functions are not handling the case for empty lists or when i is greater than the length of the list; hence they're not exhaustive.