Ninety-Nine Haskell Problems 5

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


五問目.

5 Problem 5

(*) Reverse a list.

Example in Haskell:

Prelude> reverse "A man, a plan, a canal, panama!"
"!amanap ,lanac a ,nalp a ,nam A"
Prelude> reverse [1,2,3,4]
[4,3,2,1]

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


とりあえず,これ.

myReverse x = reverse x

しかし,これではなんの意味もないので別解.
fold系(こういう分類はおかしいのか?)が使えそう.ていうか,reverseの定義がそんなだった気がするけど,とりあえず自分で作る.

myReverse :: [a] -> [a]
myReverse' x = foldl (flip (:)) [] x

実際,reverseも同じように定義されている.最初foldrを使おうとして,若干時間がかかったけど,最終的にこの定義にたどりついた.
ところで,一問目のときに,このfoldlを使ったものより,

reverse l =  rev l []
  where
    rev []     a = a
    rev (x:xs) a = rev xs (x:a)

って定義のほうがわかりやすいとか言ってたくせに,いまこの定義は思いつけなかった.まったく馬鹿だぜ,はは.今見ても,こっちのほうが,僕は好きなんだけどな.
まぁいいや.ということで解答.

Solution: (defined in Prelude)

reverse          :: [a] -> [a]
reverse          =  foldl (flip (:)) []

The standard definition is concise, but not very readable. Another way to define reverse is:

reverse :: [a] -> [a]
reverse [] = []
reverse (x:xs) = reverse xs ++ [x]

However this definition is more wasteful than the one in Prelude 
as it repeatedly reconses the result as it is accumulated. 
The following variation avoids that, and thus computationally closer to the Prelude version.

reverse :: [a] -> [a]
reverse list = reverse' list []
  where
    reverse' [] reversed     = reversed
    reverse' (x:xs) reversed = reverse' xs (x:reversed)

なんでこんなに長いんだよ…….
書いてあるように,foldlを使ったものは,簡潔だけど読みにくい.一問目のときに大分苦労した.
で,次の,

reverse :: [a] -> [a]
reverse [] = []
reverse (x:xs) = reverse xs ++ [x]

は,おお!わかりやすい!って感じなんだけど,foldlによる定義より無駄が多いのだそうだ.しかし,英語がわからなくていまいちわからない.as it repeatedly reconses the result as it is accumulatedってなんのこっちゃ.わからないけど,一回全部リストにしてから足し合わせるってのが無だってことかな?たしかに,メモリは無駄な気がするけど,やっぱり速度も遅くなるのかな.
で,最後のは一問目のときにも見た定義.
よし.おしまい.

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