99 questions/Solutions/3

From HaskellWiki
< 99 questions‎ | Solutions
Revision as of 20:44, 13 July 2012 by Wi (talk | contribs)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

(*) Find the K'th element of a list. The first element in the list is number 1.

This is (almost) the infix operator !! in Prelude, which is defined as:

(!!)                :: [a] -> Int -> a
(x:_)  !! 0         =  x
(_:xs) !! n         =  xs !! (n-1)

Except this doesn't quite work, because !! is zero-indexed, and element-at should be one-indexed. So:

elementAt :: [a] -> Int -> a
elementAt list i = list !! (i-1)

Or without using the infix operator:

elementAt' :: [a] -> Int -> a
elementAt' (x:_) 1 = x
elementAt' [] _ = error "Index out of bounds"
elementAt' (_:xs) k
 | k < 1     = error "Index out of bounds"
 | otherwise = elementAt' xs (k - 1)

Alternative version:

elementAt'' :: [a] -> Int -> a
elementAt'' (x:_) 1 = x
elementAt'' (_:xs) i = elementAt xs (i - 1)
elementAt'' _ _ = error "Index out of bounds"

This does not work correctly on invalid indexes and infinite lists, e.g.:

elementAt'' [1..] 0

A few more solutions using prelude functions:

elementAt_w' xs n = last . take n $ xs -- wrong
-- Main> map (elementAt_w' [1..4]) [1..10]
-- [1,2,3,4,4,4,4,4,4,4]
elementAt_w'' xs n = head . reverse . take n $ xs -- wrong
-- Main> map (elementAt_w'' [1..4]) [1..10]
-- [1,2,3,4,4,4,4,4,4,4]
elementAt''' xs n = head . drop (n - 1) $ xs
or
elementAt_w'
correctly in point-free style:
elementAt_w'pf = (last .) . take . (+ 1)