Ninety-Nine Haskell Problems 3

1to10 11to20 21to30 31to40 51to60 61to70 71to80 81to90 91to99 all
Ninety-Nine Haskell Problems


三問目.
問題.

3 Problem 3

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

Example:

(element-at '(a b c d e) 3)
C

Example in Haskell:

Prelude> elementAt [1,2,3] 2
2
Prelude> elementAt "haskell" 5
'e'

http://www.haskell.org/haskellwiki/99_questions/1_to_10#Problem_3

おいおい,これは簡単すぎるじゃないか?というか,昨日見たぞ.
とりあえず,

elementAt x n = x !! (n-1)

は,うまくいく.というか,こんな感じで文字列もリストと同じように扱えるんだ.すごい.


次に,昨日見た!!のソースと似たような定義の仕方.

elementAt' x 1 = head x
elementAt' (x:xs) n = elementAt' xs (n-1)

これだけだと,なにも考え付いてないので,さらなる別解を.
なかなか思いつかなかったけど,一行で出来た.

elementAt''' x n = reverse x !! ((length x)-n)

リストを逆転させて数えるっていう.若干まどろっこしいけど.

さて,解答.

Solution:

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)

おやまぁ,長い.でも最初に書いてあるのは!!の定義.で,これをそのまま使うのではだめだから,第二引数の値から1引いて,!!しましょうってこと.僕の一つ目と同じ.よっしゃ.
解答の二つ目も,考え方は同じ.デクリメントしつつリストを削って,ちょうどいいときに「これ!」ってさしだす.
縦線|はkについての条件かな.k<1のときはerror "Index out of bounds"で,それ以外のときはelementAt' xs (k - 1)を実行.
三問目はもうおしまい.これぐらいの分量だと丁度いい.というか,ちょっと物足りない.
でも,思ったのが,「型を明示しよう」ということと,「エラー処理をちゃんとやろう」ということ.エラー処理で甘えるとかいかんね.これが三問目で得たこと.

1to10 11to20 21to30 31to40 51to60 61to70 71to80 81to90 91to99 all
Ninety-Nine Haskell Problems