Reputation: 290
How to create a function in Haskell that returns the fifth element from a list.
Something like this:
fifth [] = []!!4
Should return this:
*Main> fifth [1,2,3,20,30,40]
30
Upvotes: 3
Views: 691
Reputation: 73798
Simply use:
fifth :: [a] -> a
fifth l = l !! 4
Using fifth []
like you suggest is wrong since that will pattern match the list against the empty list — you simply want to bind a variable name to the full list so that you can use the !!
function afterwards.
You can even define the function as:
fifth :: [a] -> a
fifth = (!!4)
Here we use partial application: you normally think of !!
as a function taking two arguments: a list and an integer. We can provide it with one of the arguments and get a new function (fifth
) that only takes a list. When we provide (!!4)
with a list, it returns the fifth element:
Prelude> let fifth = (!!4)
Prelude> fifth [1,2,3,20,30,40]
30
The function is of course a partial function since it will fail for small lists:
Prelude> (!!4) [1,2,3,20]
*** Exception: Prelude.(!!): index too large
That's to be expected. If you want, you can make it safe by letting it return Maybe a
instead of a
::
fifth :: [a] -> Maybe a
fifth (a:b:c:d:e:rest) = Just e
fifth _ = Nothing
Here the first pattern will match lists of length 5 or more, and the second pattern matches anything not matched by the first. You use it like this:
*Main> fifth [1,2,3,20,30,40]
Just 30
*Main> fifth [1,2,3,20]
Nothing
You have now forced yourself to always pattern match the result of fifth
against either Just a
or Nothing
. This means that when you code calls fifth someList
, then it must take into account that someList
might be too short. That way you can ensure at compile time that there wont be any runtime errors from this function.
Upvotes: 12
Reputation: 36339
Another unsafe variant would be
fifth = head . drop 4
But hey, sometimes one just knows this damn list will have more than 4 elements. The type system is just not powerful enough to express it (using standard lists, that is).
Upvotes: 5
Reputation: 92106
I would define a safe-indexing operator !!!
and then define fifth
in terms of !!!
.
(!!!) :: [a] -> Int -> Maybe a
xs !!! n | n < 0 = Nothing
[] !!! _ = Nothing
(x : _) !!! 0 = Just x
(_ : xs) !!! n = xs !!! (n - 1)
fifth :: [a] -> Maybe a
fifth = (!!! 4)
Upvotes: 8