integral007
integral007

Reputation: 290

Haskell - how to create a function that returns the fifth element from a list

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

Answers (3)

Martin Geisler
Martin Geisler

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

Ingo
Ingo

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

missingfaktor
missingfaktor

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

Related Questions