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
の長さに合わせてインデックスを取り出すため、問題なく動作します。