Haskell勉強会

関数型プログラミングの学習日記

Scala関数型デザイン&プログラミング ― Scalazコントリビューターによる関数型徹底ガイド

Scalaの教材が紹介されていました。

 

dev.classmethod.jp

 

この記事で紹介されていた「Scala関数型デザイン&プログラミング」という本が良書だったのでメモ。

 

 

 

目次

 

Part I 関数型プログラミングの基礎

 

第1章 関数型プログラミングとは

 

 1.1 関数型プログラミングの利点:単純な例

  1.1.1 副作用を持つプログラム

  1.1.2 関数型プログラミングのソリューション:副作用の排除

 1.2 関数とはいったい何か

 1.3 参照透過性、純粋性、置換モデル

 1.4 まとめ

 

第2章 Scala関数型プログラミングの準備

 

 2.1 速習:Scala言語

 2.2 プログラムの実行

 2.3 モジュール、オブジェクト、名前空間

 2.4 高階関数:関数に関数を渡す

  2.4.1 関数型のループ

  2.4.2 高階関数の作成

 2.5 多相関数:型の抽象化

  2.5.1 多相関数の例

  2.5.2 無名関数を使った高階関数の呼び出し

 2.6 型に従う実装

 2.7 まとめ

 

第3章 関数型プログラミングのデータ構造

 

 3.1 関数型データ構造の定義

 3.2 パターンマッチング

 3.3 関数型データ構造でのデータ共有

  3.3.1 データ共有の効率性

  3.3.2 高階関数型推論の改善

 3.4 リストの再帰高階関数の一般化

  3.4.1 リストを扱うその他の関数

  3.4.2 より単純なコンポーネントからリスト関数を組み立てるときの非効率性

 3.5 ツリー

 3.6 まとめ

 

第4章 例外を使わないエラー処理

 

 4.1 例外の光と影

 4.2 例外に代わる手法

 4.3 Optionデータ型

  4.3.1 Optionの使用パターン

  4.3.2 Optionの合成、リフト、例外指向のAPIラッピング

 4.4 Eitherデータ型

 4.5 まとめ

 

第5章 正格と遅延

 

 5.1 正格関数と非正格関数

 5.2 遅延リストの例

  5.2.1 ストリームを記憶し、再計算を回避する

  5.2.2 ストリームを検査するためのヘルパー関数

 5.3 プログラムの記述と評価の切り分け

 5.4 無限ストリームと余再帰

 5.5 まとめ

 

第6章 純粋関数型の状態

 

 6.1 副作用を使った乱数の生成

 6.2 純粋関数型の乱数の生成

 6.3 ステートフルAPIの純粋化

 6.4 状態の処理に適したAPI

  6.4.1 状態アクションの結合

  6.4.2 入れ子の状態アクション

 6.5 状態アクションデータ型の一般化

 6.6 純粋関数型の命令型プログラミング

 6.7 まとめ

 

Part II 関数型デザインとコンビネータライブラリ

 

第7章 純粋関数型の並列処理

 

 7.1 データ型と関数の選択

  7.1.1 並列計算のためのデータ型

  7.1.2 並列計算の結合

  7.1.3 明示的なフォーク

 7.2 表現の選択

 7.3 APIの改良

 7.4 APIの代数

  7.4.1 マッピングの法則

  7.4.2 フォークの法則

  7.4.3 法則への違反:バグ

  7.4.4 アクターを使ったParの完全なノンブロッキング実装

 7.5 コンビネータを最も汎用的な形式に改良する

 7.6 まとめ

 

第8章 プロパティベースのテスト

 

 8.1 速習:プロパティベースのテスト

 8.2 データ型と関数の選択

  8.2.1 API:最初のコード

  8.2.2 プロパティn意味とAPI

  8.2.3 ジェネレータの意味とAPI

  8.2.4 生成された値に依存するジェネレータ

  8.2.5 Propデータ型の改良

 8.3 テストケースの最小化

 8.4 ライブラリの使用とユーザビリティの改善

  8.4.1 単純な例

  8.4.2 並列処理のためのテストスイートの作成

 8.5 高階関数のテストと今後の展望

 8.6 ジェネレータの法則

 8.7 まとめ

 

第9章 パーサーコンビネータ

 

 9.1 代数の設計から始める

 9.2 代数の例

  9.2.1 スライスと空ではない繰り返し

 9.3 文脈依存への対処

 9.4 JSONパーサーの作成

  9.4.1 JSONの書式

  9.4.2 JSONパーサー

 9.5 エラー報告

 9.6 代数の実装

 9.7 まとめ

 

Part III 関数型デザインに共通する構造

 

第10章 モノイド

 

 10.1 モノイドとは

 10.2 モノイドによるリストの畳み込み

 10.3 結合性と並列性

 10.4 並列解析の例

 10.5 畳み込み可能なデータ構造

 10.6 モノイドの合成

  10.6.1 より複雑なモノイドの構築

  10.6.2 合成されたモノイドを使った走査の融合

 10.7 まとめ

 

第11章 モナド

 

 11.1 ファンクタ:map関数の一般化

  11.1.1 ファンクタ則

 11.2 モナド:flatMapと単位関数の一般化

  11.2.1 モナドトレイト

 11.3 モナドコンビネータ

 11.4 モナド

  11.4.1 結合律

  11.4.2 特定のモナドに対する結合律の証明

  11.4.3 同一律

 11.5 モナドとはいったい何か

  11.5.1 単位元モナド

  11.5.2 Stateモナドと部分的な型の適用

 11.6 まとめ

 

第12章 アプリカティブファンクタとトラバーサブルファンクタ

 

 12.1 モナドの一般化

 12.2 アプリカティブトレイト

 12.3 モナドとアプリカティブファンクタの違い

  12.3.1 OptionアプリカティブとOptionモナド

  12.3.2 ParserアプリカティブとParserモナド

 12.4 アプリカティブファンクタの利点

  12.4.1 モナドではないアプリカティブファンクタ

 12.5 アプリカティブの法則

  12.5.1 左単位元と右単位元

  12.5.2 結合性

  12.5.3 積の自然性

 12.6 トラバーサブルファンクタ

 12.7 Traverseの使用

  12.7.1 モノイドからアプリカティブファンクタへ

  12.7.2 Stateを使った走査

  12.7.3 トラバーサブルな構造の結合

  12.7.4 走査の融合

  12.7.5 入れ子の走査

  12.7.6 モナドの合成

 12.8 まとめ

 

Part IV 作用とI/O

 

第13章 外部作用とI/O

 

 13.1 作用のリファクタリング

 13.2 単純なIO型

  13.2.1 入力作用の処理

  13.2.2 単純なIO型の長所と短所

 13.3 StackOverflowErrorの回避

  13.3.1 制御フローをデータコンストラクタとして具体化する

  13.3.2 トランポリン化:スタックオーバーフローに対する一般的な解決策

 13.4 より高機能なIO型

  13.4.1 フリーモナド

  13.4.2 コンソールI/Oだけをサポートするモナド

  13.4.3 純粋なインタープリタ

 13.5 ノンブロッキングの非同期I/O

 13.6 汎用目的のIO型

  13.6.1 宇宙の果てのメインプログラム

 13.7 なぜIO型ではI/Oのストリーミングに不十分なのか

 13.8 まとめ

 

第14章 局所作用とミュータブルな状態

 

 14.1 純粋関数型の変更可能な状態

 14.2 副作用のスコープを適用するためのデータ型

  14.2.1 変更処理にスコープを適用するための小さな言語

  14.2.2 ミュータブルな参照の代数

  14.2.3 ミュータブルな状態アクションの実行

  14.2.4 ミュータブルな配列

  14.2.5 純粋関数型のquicksort

 14.3 純粋性とコンテキスト

  14.3.1 副作用と見なされるのは何か

 14.4 まとめ

 

第15章 ストリーム処理とインクリメンタルI/O

 

 15.1 命令型I/Oの問題:例

 15.2 単純なストリームトランスデューサ

  15.2.1 プロセスの作成

  15.2.2 プロセスの合成と追加

  15.2.3 ファイルの処理

 15.3 拡張可能なProcess型

  15.3.1 ソース

  15.3.2 リソースの安全性の確保

  15.3.3 単一入力の処理

  15.3.4 複数の入力ストリーム

  15.3.5 シンク

  15.3.6 エフェクトフルなチャネル

  15.3.7 リソースの動的な割り当て

 15.4 応用

 15.5 まとめ

 

索引

 

著者紹介

Paul Chiusano(ポール・キウザーノ)

Scala関数型プログラミングなどのソフトウェア開発コンサルタント。2008年以降、Scalaによる関数型プログラムを商用ベースで展開。

https://twitter.com/pchiusano

 

Rúnar Bjarnason(ルナー・ビャルナソン)

プログラマー歴は12年。2008年から関数型プログラミングに注力。関数型プログラミングScalaプログラミングをテーマにブロガーやスピーカーとして活躍中。ScalazライブラリやJava関数型ライブラリ開発の主要なコントリビューターである。

https://twitter.com/runarorama

 

出版社情報

https://book.impress.co.jp/books/1114101091

book.impress.co.jp

 

書評

本書は英語の原著を翻訳した本です。

 

Functional Programming in Scala

Functional Programming in Scala

 

 

Amazonで見ると、原著の英語版もレビューはおおむね高評価ですね。

しかし、星が1つの低評価もありました。

気になったので、一応見てみました。

 

Steven A. Lowe

Worst. Programming. Book. Ever.

2016年3月11日にアメリカ合衆国でレビュー済み

 

This is the worst programming book I've ever tried to read. It may be good if you have insomnia, as I fell asleep reading it numerous times. It started off well for a few pages, in fact each chapter starts off fairly well for the first few pages, but just when you think the author is about to really dig in and explain the point, revealing the deep structure and subtle nuances promised by the prose, he gives you exercises and tells you to go write some code and figure it out yourself. Apparently the author's idea of "fun" is -- and I quote -- struggling with the exercises.
Seriously, if I wanted to flail around and fail for hours before stumbling on a solution, I would just open a Scala reference web page and start hacking. The "answers" to the exercises are available online, but if I have to go online to understand what the book is telling me then why did I buy, you know, a book?
This book sucks all the fun out of functional programming, fails to teach the reader (and no, I'm not a novice programmer, and yes, I am familiar with category theory), and is extremely frustrating. I only made it through the first 180 pages before throwing it away in disgust.
I got more out of an hour on Twitter's Scala School.

 

(DeepL翻訳) 

今まで読もうとしたプログラミングの本の中で一番ひどい本です。不眠症の人にはいいかもしれませんが、私は何度も読みながら寝てしまいました。実際、各章の最初の数ページはかなりいい感じで始まるのですが、著者が本当に掘り下げて要点を説明し、散文で約束された深い構造や微妙なニュアンスを明らかにしようとしていると思ったら、練習問題を与えて、コードを書いて自分で考えろと言うのです。どうやら著者の考える「楽しみ」とは、引用すると「練習問題と格闘すること」のようだ。
真面目な話、もし私が何時間も悩んだり失敗したりして解決策にたどり着きたかったら、ScalaのリファレンスWebページを開いてハッキングを始めるでしょう。練習問題の「答え」はオンラインで見ることができますが、本の内容を理解するためにオンラインに行かなければならないのであれば、なぜ本を買ったのでしょうか?
この本は、関数型プログラミングの楽しみを奪い、読者に教えることもできず(私は初心者プログラマーではありませんし、圏論にも精通しています)、非常にイライラさせられます。私は最初の180ページを読み終えただけで、うんざりして投げ出してしまいました。
TwitterScala Schoolの1時間の方がよっぽど充実していました。

 

サンプルコードをGitHubからダウンロードしなければいけないのは、それほど利便性が低いとは思いません。

ネットが普及した時代なので、説明が本だけで完結しておらず、オンラインのデータ(GitHubなど)を参照しなければならない、という不満は時代遅れなのでは?

…しかし、ネットがない環境で勉強することは多々あると思うので、不満に感じる人がいるのも理解できます。

 

 

個人的には、本書はファンクターやモナドなど、圏論に関係する関数型プログラミングの知識を図解などで分かりやすく説明することを試みた本だと思いました。

一般的なHaskellの本や圏論の本では、いまいち分かりにくいと思った人は、本書を読めば、別な角度からモナドの説明によって理解が深まると思います。

 

普段Scalaを使っていない人でも、関数型プログラミングの汎用的な知識を得ることができるので一読の価値があると思います。

もっとも、Haskell圏論を既に十分に解している人なら、不要かもしれません。

 

関数型プログラミング圏論の説明方法として、本書のスタイルは参考になりました。