2026-08-23
Compress.hs
compress :: Eq a => [a] -> [a]
compress (x:rest@(y:_))
| x == y = compress rest
| otherwise = x : compress rest
compress xs = xs
main :: IO ()
main = print (compress [1, 1, 2, 2, 2, 3, 1, 1] :: [Int])
rest@(y:_)というas-patternに注目してください。これは何を出力するでしょうか?
Answer
[1,2,3,1](その後に改行)。compressは連続する重複要素を1つに畳む純粋関数です。rest@(y:_)は、リストの2番目以降をy:_というパターンで調べつつ、同時にその全体をrestという名前でも束縛します(as-pattern)。もしyを取り出すためだけに(y:ys)と書いてしまうと、次に必要な「2番目以降のリストそのもの」はy:ysとして自分で組み直すことになりますが、restという名前で既に持っているのでその必要がありません。評価はx=1,y=1で等しいので1を捨ててcompress [1,2,2,2,3,1,1]へ進み、以下同様に隣り合う重複をすべて畳んでいくと、最終的に[1,2,3,1]に落ち着きます。compress自身は同じ入力に対して常に同じ結果を返す純粋関数ですが、それを画面に出すprint・mainは副作用のあるIO ()です。