概要
長い歴史のある関数プログラミング。
メジャーな命令型言語の最近のバージョンでは, 関数プログラミングの要素を取り入れた機能が入ってきました。
使っている言語の新機能をうまく活用し, より良い開発につなげるには, 今, 関数プログラミングを押さえておくことは効果的ではないでしょうか。
しかし, 関数プログラミングにおける思考方法は, よく知られた構造化プログラミングやオブジェクト指向プログラミングのそれとは大きく違う面があります。
書き方がわかっても, 考え方が伴わなければ, プログラムとはそうそう書けるものではありません。
本書では, 関数プログラミングのエッセンスを厳選解説。
関数型言語Haskell最新版を用いつつ, 現場の方々に向けて, Java 8, C++11, C言語, JavaScript, Rubyをはじめ, 各種の命令型言語との比較や, 言語固有の新機能の活用術, 注意点も豊富に盛り込みました。
加えて, オススメの開発/設計テクニックと題し, トップダウンの思考法や, 言語の強みを活かす技法もステップバイステップで紹介します。
広くエンジニアの方々へ, 関数型言語でも命令型言語でも活かせる「使える基本」が身に付く1冊をお届けします。
こんな方におすすめ
簡潔なコードを書きたい方 安全でバグらせにくい, 正しいコードの設計/実装に関心のある方々 JavaやC++などメジャーな命令型言語の新機能と関数型言語の関係に興味をお持ちの方々
本書に関するお知らせ
本書に関連する記事を公開しております。
大川徳之(おおかわのりゆき) 東京大学計数工学科数理情報工学コース, 東京大学大学院情報理工学系研究科数理情報学専攻, 卒業。キヤノンソフトウェア㈱を経て, 現在は㈱朝日ネットにて, HaskellでのWebアプリケーション開発や, 開発環境/インフラの構成管理などに携わっている。そろそろどうにかしてAgdaで仕事ができないものか虎視眈々と隙を窺っている。最近ご無沙汰だけどHaskell golfチョットデキル。
サポート
正誤表
本書掲載の記述に誤りがありました。ここに訂正し, 深くお詫び申し上げます。
(2016年11月28日更新)
※以下, 第1刷以降, および電子版が該当。
P.68 注4
誤
... デバッガとその使いさすさの重要性が ...
正
... デバッガとその使いや すさの重要性が ...
P.81 本文1行め
誤
不適切な変更後のC言語プログラム(リスト1.10)
正
不適切な変更後のC言語プログラム(リスト1.9 )
P.117 ページ内一番下のghciにおける実行例 下から6行めと、その出力
誤
Prelude> ([1::Int] ++ [2::Int]) :: Double
<interactive>:2:2:
Couldn't match expected type ‘Double’ with actual type ‘[Int]’
In the expression: ([1 :: Int] ++ [2 :: Int]) :: Double
In an equation for ‘it’: it = ([1 :: Int] ++ [2 :: Int]) :: Double
正
Prelude> ([1::Int] ++ [2::Int]) :: [Double]
<interactive>:2:3:
Couldn't match expected type ‘Double’ with actual type ‘Int’
In the expression: 1 :: Int
In the first argument of ‘(++)’, namely ‘[1 :: Int]’
In the expression: ([1 :: Int] ++ [2 :: Int]) :: [Double]
P.135 2行め
P.148 3行め
誤
12と15の最小公倍数である3
正
12と15の最大公約数 である3
P.154 ページ内のSquare.hs
P.161 下から3行め
誤
あるガード条件が疑になったとき
正
あるガード条件が偽 になったとき
P.193 下から8行め〜
誤
tarai 10 20 ...という形になるため, この時点yがx以上であることが判明し, 3つめの引数を計算するまでもなく結果として20を得られるはずです.
正
tarai1 4 ...という形になるため, この時点でyがx以上になっている ことが判明し, 3つめの引数を計算するまでもなく結果として4 を得られるはずです.
P.194 図4.1:C++版たらい回し関数の様子
誤
正
P.194 図4.2:Haskell版たらい回し関数の様子
誤
正
P.205 簡約パターンの2つめのリストの, 1行め〜2行め
誤
(\x -> x + x) ((\x -> x + x) a)
正
(\x -> x + x) ((\x -> x + x) 1 )
P.224 2行め
P.225 下から2行め
P.226 リスト5.1:キャプション
P.227 リスト5.2:キャプション
P.228 最下行
P.238 1つめのサンプルコード中(2)のコメント
誤
yにアクションgに適用
正
yにアクションgを 適用
P.238 12行め
誤
yにアクションgに適用
正
yにアクションgを 適用
P.242 eval exprのコード内の4行めおよび5行め
誤
toBinOp sop >>= ¥b ->
toNum sb >>= ¥c ->
正
toBinOp sop >>= ¥op ->
toNum sb >>= ¥b ->
P.246 ページ中ほどのサンプルコード内の1行めおよび2行め内
P.249 10-11行め
誤
アクション同士を組み合わせ
正
アクション同士の 組み合わせ
P.261 「副作用を扱えるのに純粋と言える理由」内:本文リスト
P.262 15-16行め
誤
なっていつ必要があります
正
なっている 必要があります
P.264 見出し「Optionalクラス」内, 1つめのリストの3行め
誤
Optional< Wallet > wallet = person.getWallet();
正
Optional< Wallet > wallet = person.get() .getWallet();
P.264 見出し「Optionalクラス」内, 1つめのリストの5行め
誤
Optiona< Money > money = wallet.getMoney(10000);
正
Optional < Money > money = wallet.get() .getMoney(10000);
P.264 見出し「Optionalクラス」内, 2つめのリストの4行め
誤
.flatMap(wallet -> wallet.getMoney(100))
正
.flatMap(wallet -> wallet.getMoney(10000 ))
P.265 見出し「メソッドチェーンの弊害」内, 1つめのリスト
誤
Optional< Person > person = persons.find("Alice");
if (person1.isPresent()) { // Aliceがいて
Optional< Pocket > pocket = person.getPocket();
if (pocket.isPresent()) { // ポケットがあって
Optiona< Money > ticket = pocket.getTicket();
if (ticket.isPresent() ) { // 引換券を持っている
Optional< Wallet > wallet = person.getWallet();
if (wallet.isPresent()) { // 財布を持っていて
Optiona< Money > money = wallet.getMoney(10000);
if (money.isPresent()) { // 10000円入っている
pay(ticket.get(), money.get());
}
}
}
}
}
正
Optional< Person > person = persons.find("Alice");
if (person1.isPresent()) { // Aliceがいて
Optional< Pocket > pocket = person.get() .getPocket();
if (pocket.isPresent()) { // ポケットがあって
Optional < Ticket > ticket = pocket.get() .getTicket();
if (ticket.isPresent() ) { // 引換券を持っている
Optional< Wallet > wallet = person.get() .getWallet();
if (wallet.isPresent()) { // 財布を持っていて
Optional < Money > money = wallet.get() .getMoney(10000);
if (money.isPresent()) { // 10000円入っている
pay(ticket.get(), money.get());
}
}
}
}
}
P.265 見出し「メソッドチェーンの弊害」内, 2つめのリスト
誤
persons
.find("Alice")
.isPresent(person -> person.getTicket()
.ifPresent(ticket -> person.getWallet()
.flatMap(wallet -> wallet.getMoney(100))
.ifPresent(money -> pay(ticket, money))))
正
persons
.find("Alice")
.isPresent(person -> person.getPocket()
.flatMap(pocket -> pocket.getTicket()
.ifPresent(ticket -> person.getWallet()
.flatMap(wallet -> wallet.getMoney(10000 ))
.ifPresent(money -> pay(ticket, money)))) )
P.265 ページ中ほどのJavaサンプルコード内の2行め
誤
if (person1.isPresent()) {
正
if (person .isPresent()) {
P.266 見出し「メソッドチェーンの弊害」内, 3つめのリスト
誤
find "Alice" persons >>= \person ->
getTicket person >>= \ticket ->
getWallet person >>= \wallet ->
getMoney 100 wallet >>= \money ->
pay ticket money
正
find "Alice" persons >>= \person ->
getPocket person >>= \pocket ->
getTicket pocket >>= \ticket ->
getWallet person >>= \wallet ->
getMoney 10000 wallet >>= \money ->
pay ticket money
P.266 見出し「メソッドチェーンの弊害」内, 4つめのリスト
誤
do person <- find "Alice" persons
ticket <- getTicket person
wallet <- getWallet person
money <- getMoney 100 wallet
pay ticket money
正
do person <- find "Alice" persons
pocket <- getPocket person
ticket <- getTicket pocket
wallet <- getWallet person
money <- getMoney 10000 wallet
pay ticket money
P.278 ページ最上部のサンプルコード内のコメント部分
P.306 サンプルコード内の上から5行めおよび下から3行め
P.330 17行め
P.351 コラム中, 3行め
P.359 14行め
P.369 26行め
誤
与える(hacking)することができます
正
与えること (hacking)ができます
P.372 2行め
以下, 第1刷のみ。第2刷以降および最新の電子版では修正済み。
P.28 注38
P.33 14行め
P.39 15行め
P.33 6行め
誤
手続きの中にであっても
正
手続きの中であっても
P.73 箇条書き1-1
誤
処理が有効値を返せば引き続きその値を有効値を返す
正
処理が有効値を返せば引き続きその値を有効値として 返す
P.74 サンプルコード最終行
P.112 図2.3中
誤
正
補足情報
P.16 見出し「F#」横のURL
URLが変更になっています(ページ内容としては同じ。2015年1月5日確認時点)
P.17 見出し「Standard ML(SML)」の参考URLについて
SML実装はかなりの数がありますが, 代表的なSML実装としてはSML/NJ(http://www.smlnj.org/ )があります。ほかにも東北大のSML#(http://www.pllab.riec.tohoku.ac.jp/smlsharp/ja/ )が産学連携でERPシステムを開発するなどしています。