Skip to content

Commit b521b0e

Browse files
committed
Introduce eta-reduction
1 parent 4620201 commit b521b0e

File tree

1 file changed

+63
-10
lines changed

1 file changed

+63
-10
lines changed

assets/18.md

+63-10
Original file line numberDiff line numberDiff line change
@@ -657,38 +657,91 @@ ghci> (4 -) 4
657657

658658
### やり過ぎ注意、あるいはどこまでやるか
659659

660-
復習を兼ねて、ここまでで紹介した種々のテクニックを活用してみましょう。文字列を処理する関数をいくつか書いて、それを短くしては拡張し、短くしては拡張し...、というサイクルを繰り返します。この課題の学習する内容と直接関係がない知識も混ざりますが、ついでに学ぶと思ってご容赦ください
660+
復習を兼ねて、ここまでで紹介した種々のテクニックを活用してみましょう。文字列を処理する関数をいくつか書いて、それを短くしてみます
661661

662662
まずは、`map`関数を使い、文字列のリストの各要素に「挨拶する」、すなわち`"Hello, "`という文字列を先頭に付け加える関数を書いてみましょう:
663663

664664
```haskell
665665
greetEach xs = map (\x -> ("Hello, " ++ x)) xs
666666
```
667667

668+
第一に、「Haskellにおける関数はカリー化されている」、つまり二つ以上の引数を受け取る関数に一つ引数を渡すと、残りの引数を受け取る関数が返ってくる、という性質を用いれば、`greetEach`の引数`xs`を省略できます:
669+
670+
```haskell
671+
greetEach = map (\x -> ("Hello, " ++ x))
672+
```
673+
674+
一般に、関数の最後の引数が、関数の本体である関数呼び出しの最後の引数として一度だけ使用されている場合、その引数は省略することができます。
675+
676+
より単純な例に置き換えると、
677+
678+
```haskell
679+
f x y z = g x y z
680+
```
681+
682+
上記の`f`関数の引数、`z``g`の最後の引数として一度だけ使われているので、
683+
684+
```haskell
685+
f x y = g x y
686+
```
687+
688+
と書き換えることができます。
689+
690+
そしてこの規則を繰り返し適用すると、`y``x`の順で省略できるようになると分かるでしょう。つまり最終的には次のように変換できます:
691+
692+
```haskell
693+
f = g
694+
```
695+
696+
シンプルになりました!
697+
698+
ちなみに、このように引数を省略する変換を、「eta reduction」と言います。
699+
668700
<!-- NOTE: この入門、`filter`について全く触れてないからここで触れようかと思ったけど、時間かかりそうだしこんなもんにしとくか... -->
669701

670-
このくらいなら序の口?
702+
もっと短くしてみましょう。今度は演算子のセクションを使って、`map`関数に渡す関数の式`(\x -> ("Hello, " ++ x))`を簡潔にします。演算子のセクションを使って、次のように「先頭に`"Hello, "`という文字列を付け加える関数」を作ることで、引数`x`を省略することができます:
703+
704+
```haskell
705+
-- これを...
706+
(\x -> ("Hello, " ++ x))
707+
708+
-- こう書き換える
709+
("Hello, " ++)
710+
```
711+
712+
新しく短くできた関数を`map`関数に渡してみましょう:
713+
714+
```haskell
715+
greetEach = map ("Hello, " ++)
716+
```
717+
718+
下記の最初のバージョンよりかなり短くできました!
671719

672720
```haskell
673-
ghci> map ("Hello, " ++) ["Tom", "Bob", "Alice"]
674-
["Hello, Tom","Hello, Bob","Hello, Alice"]
721+
greetEach xs = map (\x -> ("Hello, " ++ x)) xs
722+
723+
-- v.s.
724+
725+
greetEach = map ("Hello, " ++)
675726
```
676727

728+
hoge
729+
730+
hoge: ポイントフリースタイルについてここで説明
731+
677732
に、末尾に「!」を加えたくなったとする。
678733

679734
```haskell
680735
ghci> map (("Hello, " ++) . (++ "!")) ["Tom", "Bob", "Alice"]
681736
["Hello, Tom!","Hello, Bob!","Hello, Alice!"]
682737
```
683738

684-
hoge: ポイントフリースタイルについてここで説明
685-
686-
さらにさらに、どんどんポイントフリースタイルにすると、読みにくくなってしまう例が: [ポイントフリースタイルへの道 〜最大公約数編〜 - Qiita][3]
739+
さらにさらに、どんどんポイントフリースタイルにすると、読みにくくなってしまう例が: [ポイントフリースタイルへの道 〜最大公約数編〜 - Qiita][1]
687740
これまでの課題で紹介していない機能も利用していますが参考までにどうぞ。
688-
大事なことは、[**短く書ける人を上級者と呼ぶな**][4]ということです。
741+
大事なことは、[**短く書ける人を上級者と呼ぶな**][2]ということです。
689742

690-
[3]: https://qiita.com/necojackarc/items/1bccc9643857d3ce7896
691-
[4]: https://wiki.haskell.jp/Hikers%20Guide%20to%20Haskell#%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E3%83%95%E3%83%AA%E3%83%BC%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%81%82%E3%82%8B%E3%81%84%E3%81%AF%E6%A7%98%E3%80%85%E3%81%AA%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%81%A8%E3%81%AE%E4%BB%98%E3%81%8D%E5%90%88%E3%81%84%E6%96%B9
743+
[1]: https://qiita.com/necojackarc/items/1bccc9643857d3ce7896
744+
[2]: https://wiki.haskell.jp/Hikers%20Guide%20to%20Haskell#%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E3%83%95%E3%83%AA%E3%83%BC%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%81%82%E3%82%8B%E3%81%84%E3%81%AF%E6%A7%98%E3%80%85%E3%81%AA%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%81%A8%E3%81%AE%E4%BB%98%E3%81%8D%E5%90%88%E3%81%84%E6%96%B9
692745

693746
### ラムダ抽象や関数の引数でのパターンマッチ
694747

0 commit comments

Comments
 (0)