クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

map・filter・foldの使い方

このレッスンのあとで: for 文の繰り返しを、map、filter、fold で置きかえることができる。

70分のレッスンコマンド7件Haskell ラボ:関数と型で学ぶ関数型プログラミングをブラウザーで

for文を書かずに繰り返す

map、filter、fold は、リストの全部の要素に関数を使うための、3つの基本部品です。for 文を書かなくても、「全部に適用する」「条件で選ぶ」「1つにまとめる」を、それぞれ1行で書けます。

レシートの金額のリストから、500円以上だけを選び、税込みにして、合計を出す場面を考えます。この3つの部品を、順につなぐだけで書けます。

このレッスンのゴール

メモ

for 文の繰り返しを、map、filter、fold で置きかえることができる。

キーワード

ことばいみれい
高階関数関数を引数として受け取る関数
mapリストの全部の要素に、関数を適用するmap (+1) [1, 2]
filter条件に合う要素だけを残すfilter even [1, 2]
畳み込みリストを1つの値にまとめる(fold)foldl (+) 0 [1, 2]
初期値畳み込みを始めるときの値

学生が入力するセルは、このプレビューでは空白です。

map は全部の要素を変える

map f list は、list の要素の1つ1つに関数 f を適用し、その結果のリストを返します。元のリストは変わりません。要素の数も同じです。

(+1) は「1を足す関数」を表す書き方です。map (+1) [1, 2, 3] は、全部の要素に1を足します。

リストの全部に 1 を足す

コマンド
docker exec haskell ghc -e 'map (+1) [1, 2, 3]'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

filter は条件に合うものを残す

filter test list は、test が True を返す要素だけを残します。test は、1つの要素を受け取って True か False を返す関数です。

残る要素の順番は、元のままです。条件に合うものが1つもなければ、空のリストを返します。

2 より大きい要素を残す

コマンド
docker exec haskell ghc -e 'filter (> 2) [1, 2, 3, 4]'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

例: 3つの金額に map と filter

金額(円)500円以上か残ったら税込み(10%)
300いいえ残らない
800はい880
1200はい1320

学生が入力するセルは、このプレビューでは空白です。

fold はリストを1つの値にまとめる

畳み込み(fold)は、リストの要素を1つずつ関数でまとめて、1つの値にします。foldl f 初期値 リスト は、左の要素から順に、結果と次の要素を f に渡します。

合計も、積も、最大値も、畳み込みで書けます。foldl (+) 0 [1, 2, 3, 4] は、0 に1、2、3、4を順に足します。

4つの数の合計を畳み込む

コマンド
docker exec haskell ghc -e 'foldl (+) 0 [1, 2, 3, 4]'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

引き算では左右で結果が変わる

foldr は、右の要素から順にまとめます。足し算なら、左から始めても右から始めても同じです。

しかし引き算は、順番で結果が変わります。下の表のとおり、foldl (-) 0 [10, 3, 2] と foldr (-) 0 [10, 3, 2] は別の値になります。

例: 引き算の左右の畳み込み

畳み込み計算の形結果
foldl (-) 0 [10, 3, 2]((0 - 10) - 3) - 2-15
foldr (-) 0 [10, 3, 2]10 - (3 - (2 - 0))9

学生が入力するセルは、このプレビューでは空白です。

左から引いていく

コマンド
docker exec haskell ghc -e 'foldl (-) 0 [10, 3, 2]'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

右から引いていく

コマンド
docker exec haskell ghc -e 'foldr (-) 0 [10, 3, 2]'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

よくある間違い

注意

「foldl と foldr は、どちらを使っても同じ結果だ」と考える人が多くいます。足し算や掛け算では同じですが、引き算や文字をつなぐ処理では、順番で結果が変わります。どちらから始めるかを、必ず意識します。

3つの部品をつなぐ

コマンド
docker exec haskell ghc -e 'sum (map (*2) (filter odd [1 .. 10]))'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

Fold.hs を動かす

コマンド
docker exec haskell runghc Fold.hs

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

Python で畳み込みの形を見る

コード: python
# for 文で書いた畳み込みです。total が「ここまでの結果」です。
def put_front(total, item):
    return item + total


total = ""
for item in ["a", "b", "c"]:
    total = put_front(total, item)
print(total)
# 中の item + total を total + item に変えて、結果がどう変わるか確かめましょう。

このラボとソースについて: Haskell ラボ:関数と型で学ぶ関数型プログラミングをブラウザーで

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。