Haskell での where 句を使う・使わない実装パターン
where 句を使うか使わないかで、Haskell のコードの可読性や関数プログラミングのスタイルがどう変わるかを比較します。
where 句を使った実装
まずは、where 句を使った実装です。このパターンでは、インデックスのリストを where 句内で定義し、インデックスを使って文字列にインデックスを追加します。
実装
addEqualsAndIndex :: [String] -> [String]
addEqualsAndIndex xs = zipWith addIndex xs indices
where
indices = [0 ..] -- インデックスのリストを生成
addIndex :: (String, Int) -> String
addIndex (s, i) = s ++ "=" ++ show i -- 文字列にインデックスを付けて返す
main :: IO ()
main = do
let result = addEqualsAndIndex ["a", "b", "c", "d", "e"]
mapM_ putStrLn result
解説
addEqualsAndIndex関数は、文字列のリストxsとインデックスのリストindicesをzipWithを使って組み合わせ、それぞれにインデックスを付け加えます。
indices = [0 ..]でインデックスのリストを生成し、zipWithでaddIndex関数を適用します。
addIndexは、文字列sとインデックスiを受け取り、s="インデックス" の形式に変換します。
where句を使わない実装
次に、where 句を使わずに、同じ処理を関数内で直接記述する方法です。ここでは、無名関数(ラムダ式)を使ってインデックスのリストと文字列を組み合わせます。
実装
addEqualsAndIndex :: [String] -> [String]
addEqualsAndIndex xs = zipWith (\s i -> s ++ "=" ++ show i) xs [0..]
main :: IO ()
main = do
let result = addEqualsAndIndex ["a", "b", "c", "d", "e"]
mapM_ putStrLn result
解説
zipWithの部分で、無名関数(ラムダ式)を使って、xsと[0..]の各要素を結びつけます。
ラムダ式(\s i -> s ++ "=" ++ show i)は、文字列sとインデックスiを受け取って、s="インデックス" の形式に変換します。
[0..]は、無限リストですが、zipWithがxsの長さに合わせてインデックスを取り出すため、問題なく動作します。