SlideShare a Scribd company logo
OOP(Swift)で説明するMonad
Roy Kim (金 成哲)
NCデザイン&コンサルティング株式会社
Swiftで、Functional Prgrammingをどう適用するか?
入る前に
2Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Who am I?
 金 成哲 (Roy S. Kim)
• @royskimJP
• kim@ncdc.co.jp
• UXデザイナー、ITコンサルタント、exエンジニア
 Work @ NCデザイン&コンサルティング株式会社
• 2011年3月に創業
• 東京4人、関西3人の体制
• 在宅勤務 & コーワーキングスペース
• 企業向けのアプリ開発・UXデザイン
• サービスデザイン → UX/UIデザイン → 実装 → 運用・改善までを支援
3
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Swift
4
>100
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Haskell
5
>30
入りながら
なぜ、モナド?なぜ、FP?
6Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
入りながら
なぜ、モナド?なぜ、FP?
7Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
関数型プログラミング
(Functional Programming)
の略
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
モナド(Monad)とは?
 Wikipediaの説明
• 圏論(けんろん)に基づいた概念
 数学の一分野である圏論において、モナド(英語: monad)あるいはトリプル
(英語: triple)とは(自己)関手と2つの自然変換の三つ組である。モナドは随伴
関手の理論で使われ、半順序集合上の閉包作用素を任意の圏の上へ一般化する。モ
ナドという名前は、対応する圏を一般化するというモナドの動作に注目して、ソー
ンダース・マックレーンが哲学用語である「モナド」を借用した。
• 関数型プログラミングにおいての説明
 モナド(monad)は計算を表現する構造であり、計算ステップの列からなる。つま
り、型がモナド構造をもつというのは、命令を繋げるやり方、言い換えるとその型
をもつ関数をネストさせる規則が定まっていることをいう。これはプログラマがパ
イプラインを作ることを可能にする。パイプラインでは入力データを1ステップず
つ処理するが、モナドは各アクションに追加の処理規則を上乗せすることができる
8
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
モナド(Monad)とは?
 Wikipediaの説明
• 圏論(けんろん)に基づいた概念
 数学の一分野である圏論において、モナド(英語: monad)あるいはトリプル
(英語: triple)とは(自己)関手と2つの自然変換の三つ組である。モナドは随伴
関手の理論で使われ、半順序集合上の閉包作用素を任意の圏の上へ一般化する。モ
ナドという名前は、対応する圏を一般化するというモナドの動作に注目して、ソー
ンダース・マックレーンが哲学用語である「モナド」を借用した。
• 関数型プログラミングにおいての説明
 モナド(monad)は計算を表現する構造であり、計算ステップの列からなる。つま
り、型がモナド構造をもつというのは、命令を繋げるやり方、言い換えるとその型
をもつ関数をネストさせる規則が定まっていることをいう。これはプログラマがパ
イプラインを作ることを可能にする。パイプラインでは入力データを1ステップず
つ処理するが、モナドは各アクションに追加の処理規則を上乗せすることができる
9
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
モナドはブリトー?
10
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Swiftは、マルチパラダイムランゲージ
 Object Oriented Programming (= OOP)
• Cocoa TouchはOOPのフレームワークなので、OOPの採用は必須
 Protocol Oriented Programming (= POP)
• アップルがWWDC2015で披露、これからのSwiftのパラダイムとして強く展開している
• オブジェクトの継承よりProtocolの採用によってより柔軟なコードになる(と言ってい
る)
• これからの正しい設計は;
 親クラスを作って継承(X)
 プロトコルを作ってそれに準拠した実装(◎)
 Value Oriented Programming (= VOP)
• Swiftのデータタイプは基本Immutable
• ImmutableなValue Typeを使うことでより安全なコードになる(と、アップルが
WWDC2015にて言っている)
• Classes=more complexity. Values=less complexity
11
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Swiftは関数型プログラミング言語でもあるのか?
 Swiftが出たら「関数型プログラミングができる!」とみん
な騒いでいるらしい!?
• 専門の書籍も出ている(下図を参照)
• 「SwiftでFunctional Programming」という題の講演とブログが流行る
• FPの手法を採用したサードパーティライブラリーがたくさん出ている
12
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
話を進める前に、関数型プログラミングとは?
 関数型プログラミングはコーディングスタイル(パラダイムでは
なく、言語の仕様でもない)
 つまり、SwiftでFPをする・しないは選択可能なオプション
 Functionが値と同等に使える
 functionを他のfunctionの引数や戻り値として使うことができる
 ソフトウェアをモジュールとして分離して考える
 小さいモジュール(関数)の組み合わせで複雑なシステムを構築する
 従って、モジュールの独立性と組み合わせの利便性が大事
 副作用(Side Effect)を避ける
 参照透明性:同じ引数で関数を呼ぶといつも同じ結果が返ってくることを
保証する
 不変性を保つ:Swiftでいう、「let」はあるけど、「var」はない
13
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Swift ≒ Haskell !?
 Swiftは先述した、関数型プ
ログラミング言語としての
要件を満たしている
• Function is first class object.
 POP、VOPは実はFPの特徴
でもある(と、言える)
 そのせいか、Haskellと
Swiftの文法の概念的類似性
が半端ない!
14
Swiftet Haskell
Protocol Type class
Protocol Extension Instanciation of
Type class
Value Oriented
Programming
Referencial
Transparancy
Optional maybe
Pattern Matching Pattern Matching
guard guard
let let
typealias type
Etc… Etc…
「Swiftって、Haskellのただのぱっくりじゃ
ないか?」と思うくらい!
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
FPとSwiftとの関係
 Swiftに登場に喜ぶFPファン達、時代の流れはFPに?
• 「新しい、しかもApple向けの開発で使えるFP言語ができた!嬉しい!」
• 海外のSwift関連媒体・イベントにはほぼ必ずFPの話が出るように!
• 「やっとFPとマーケットが巡り合った時代になった!」と喜ぶ(MSの)
人も。
15
https://channel9.msdn.com/Shows/Going+Deep/Bria
n-Beckman-Dont-fear-the-Monads
Brian Beckman: Don't fear
the Monad
Monadを楽しそうに説明してくれる。彼は簡単
だと言っているけど、多分、それはかなり主観
的な話。しかし、結構いい参考にはなる。
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
手続き型プログラミング・OOP
ハードウェアを意識した世界
操作手順(レジスターやメモーリの操作など)を記述することで問題を解決
関数型プログラミング
きれいな数学の世界。
解決方法の記述(関数の繋がり)で問題を解決
プログラミングにおける二つのアプローチ
16
10101000110110110110101101101101110111011010001011
10110111011011010100011011011011010110110110111011
10110100010111011011101101
101010001101101101101011011011011101110110
ボトム
アップ
トップ
ダウン
プログラム
図とサンプルコードで見るFPの考え方
17Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
FPの概念図
18
Int
String
Function
(+)
Value(値)
 全ては値(Value)
 つまり、関数も値
• Objective-Cでは値として使える関数はBlockのみ
• Swifitは全てが関数であり、Closureは無名関数
List
[ ]
Function
(*)
Function
(%)
Custom
Data Type
Bool
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
サンプル:値としての関数の使用例
19
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
FPの概念図
20
Int
(1)
Function
(+)
Value(値)
 同じ引数を与えると必ず同じ結果が得られる
• 「足し算」という関数に1と2を引数に渡すと必ず3が返ってくる。
• これが「参照透過性がある」ということ。(Referencial Transparancy)
Int
(2)
Int
(3)
いつやっても、何度
やっても同じ返り値
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
FPの概念図
21
Int
(1)
Function
(+)
Value(値)
 全ては厳格な型システムによって管理される
• 例えば、「足し算」は数字型を二つ引数にもらって、計算結果をまた数
字型で返す型を持つ関数
Int
(2)
Int
(3)
Int型の足し算を行う関数の型は
(Int, Int) -> Int
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
FPの概念図
22
Int
(1)
Function
(+)
Value(値)
 部分適用した関数が作れる
• 複数の引数が必要な関数に一部の引数だけを与えると、その引数をデ
フォルト値として持つ新しい関数ができる
• これは、Swiftでもできるよね?
Function
(+1)
一つだけの引数を必要とする、新しい値(関数)の出来上がり!
これは関数の部分適用による関数のカリー化と言う。
この関数の型は、(Int) -> Int
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
FPの概念図
23
Int
(2)
Function
(*)
Value(値)
 関数をつなぐことでより複雑な処理ができる
• これはOOPのMethod Chainingに似ている
Function
(+1)
Int
(3)
Int
(7)
Intの6が次の関数
の引数となる。
引数6と関数が持って
いる値1を足してその
結果を返す
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
サンプル:関数の部分適用と連鎖
24
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Functional Programming
FPの概念図
25
Input
Function
Value(値)
 FPはこれらの関数をつなぐことで必要なプログラムを実装
する
• 数学的な関数の記述
• どう処理するかではなく、何であるかの記述
Output
Function
Function
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Real World Functional Programming
FPの概念図
26
Input Function
Value(値)
 しかし、我らの世界はピュアではない!
• ピュアな心だけでは生きていけない!
• 不純なことにどう対応するか?
Output
副作用(Side Effect)の
ない、純粋な世界
Function
Function
多様に変化する不純な
(?)世界
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Real World Functional Programming
FPの概念図
27
Input Function
Value(値)
 汚れ仕事は他人に任せる!
• IOアクションという、外部とのやり取りを代行する関数を使う
• IOアクションはできるだけ小さく抑える == 不純なものは最小限に!
Output
副作用(Side Effect)の
ない、純粋な世界
Function
Function
多様に変化する不純な
(?)世界
IO
アクション
IO
アクション
二つの世界の接点であり、
関門でもあるIOアクション
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
アプリ
FPを採用したアプリ設計のあるべき姿?
28
iOS SDK
Core OS
Core Service
Media
Cocoa Touch
Inherited
Object
ValueFunction
Real World
Functional Programming
Input
Function
Output
Function Function
IO
アクション
IO
アクション
ValueFunction
Conversion
Object & ValueObject
Object
Function
Function
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
アプリ
FPを採用したアプリ設計のあるべき姿?
29
iOS SDK
Core OS
Core Service
Media
Cocoa Touch
Inherited
Object
ValueFunction
Real World
Functional Programming
Input
Function
Output
Function Function
IO
アクション
IO
アクション
ValueFunction
Conversion
Object & ValueObject
Object
Function
Function
仲介レイヤー
• Cocoa Touch、3rd Partyライブラ
リーとの連携
• 外部との連携(ネットワーク処理、
ファイルI/O、ユーザー入力の処理な
ど)
• このレイヤーをできるだけ薄くする
のがいい設計(とされている)
FP World
• 値と関数の型の定義
• 関数の実装
• アプリの機能はここで実装
OOP World
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
アプリ
しかし課題は残る!
30
iOS SDK
Core OS
Core Service
Media
Cocoa Touch
Inherited
Object
ValueFunction
ValueFunction
Conversion
Object & ValueObject
Object
Function
Function
 事実上、関数型プログラミングで純粋に
実装するにはCocoa Touchの存在感が大
きすぎる
 値をValueとして取り扱うのは難しい
• CoreDataも、Realmも、データの表現には
Objectを使っている
• それらを、FPをするために、都度Value Type
に変換するか?(冗談はやめて〜)
 ベストプラクティスはまだ定まってない
• FPとOOPの二つの世界の境界をどこに置くか、
またその仲介をどうするかの考慮が必要
やっと本題
なぜMonad?
31Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
ここで復習
32
Value(値)
 FPは関数をつなげることでやりたいことを実現する
• 関数を繋げる == メソッドチェーン
Int
(2)
Function
(*)
Function
(+1)
Int
(3)
Int
(7)
Intの6が次の関数
の引数となる。
引数6と関数が持って
いる値1を足してその
結果を返す
6
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
関数の再利用
33
Value(値)
 FPは関数を定義し、それを組み合わせることで処理を実行
する
 (+1)という関数(plusOne)をせっかく作ったので、多様な
シーンで活用したい!
Function
(+1)
使いまくるぜ〜!
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
 しかし、このような場合はどうする?
• 例えば、引数がOptionalなら??
関数を再利用する場合の課題
34
Int
(2)
Function
(/)
Function
(+1)
Int
(0)
Int
(7)
計算できないので
Nonが次の関数の
引数となる
Optional型をどう処理
するか?
Int?
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Function
(+1)
 しかし、このような場合はどうする?
• 例えば、引数がOptionalなら??
関数を再利用する場合の課題
35
Int
(2)
Function
(/)
Int
(0)
Int
(7)
計算できないので
Nonが次の関数の
引数となる
Optional型をどう処理
するか?
Int?
If文で対応できる
ぜ!
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
関数を再利用する場合の課題
36
Value(値)
 このような場合はどうする?
• 例えば、引数が配列なら??
Int
(2) Function
(tripleValue)
Function
(+1)
Int
(7)
配列が次の関数の
引数となる
配列をどう処理す
るか?
[2,2,2,]
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
関数を再利用する場合の課題
37
Value(値)
 このような場合はどうする?
• 例えば、引数が配列なら??
Int
(2) Function
(tripleValue)
Function
(+1)
Int
(7)
配列が次の関数の
引数となる
配列をどう処理す
るか?
[2,2,2,]
forループ文で
対応できるぜ!
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
しかし、これは関数型プログラミングではない
38
Value(値)
 やりたいのは関数をつなぐこと
 条件分岐やループ文を書いていてはOOPと同じ
• (まあ、悪いとは言わないが、FP的ではない!)
これらを、
排除したいのだ!
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
何が問題なのか?
39
Value(値)
 値だけを取り扱うには問題がない
 しかし、値がOptionalの中にあるか、配列の中に格納されていれ
ば、そのままでは使えない
• OptionalはIntではない、ArrayもIntではない。つまり、データ型が違う!
Int
Function
(+1)
Int
Optional
IntInt
Int
Array
Int型だけ、
受付るよ〜
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
ここで文脈、あの有名な「箱」が登場
40
Value(値)
 このような値が何かの状態をもっていることを「文脈の中にある」と
表現する
 文脈はよく「箱」と比喩される
• 多様な文脈が存在するし、自作することもできる
Int
Int
Optional
IntInt
Int
Array
• 値のみ
• 文脈がないのでこのまま使える
• 値が文脈の中にある。
• Optionalは「値があるかもないかもしれない」
という意味の文脈
• 値が文脈の中にある。
• 配列は「値がいくつあるかしれない」という意
味の文脈
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
じゃあ、どうするか?
41
Value(値)
 なら、文脈の中から値だけ抜き出せばいい!
 すると、関数が適用できるよ〜
Int
Function
(+1)
Int
Optional
IntInt
Int
Array
Int
Int
Int
Int
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
じゃあ、どうするか?
42
Value(値)
 OOPでif分やforループでやってたのがまさにこれ!
• つまり、値がどの文脈に入っているかによって、取り出す方法が異なる
Int
Function
(+1)
Int
Optional
IntInt
Int
Array
Int
Int
Int
Int
Ifでやってた!
Forループで
やってた!
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
もっと行儀よくしようぜ!
43
Value(値)
 値を文脈の中から取り出して、関数の適用が終わったら、また元
の文脈の中に入れてあげる!
• サービス精神旺盛!
Function
(+1)
Int
Optional
IntInt
Int
Array
Int
IntInt
Int
Int
Optional
IntInt
Int
Array
Int
Int
Int
Int
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
ちょっと待って、この処理は汎用化できないか?
44
Value(値)
 文脈は異なっても、やっていることは同じ
• 文脈から値を取り出す ⇒ 関数を適用する ⇒ 元の文脈の中に値を返す
Function
(+1)
Int
Optional
IntInt
Int
Array
Int
IntInt
Int
Int
Optional
IntInt
Int
Array
Int
Int
Int
Int
Function
(+1)
文脈から値を取り出す 値に関数を適用 値を元の文脈の中に返す
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
ちょっと待って、この処理は汎用化できないか?
45
Value(値)
 文脈は異なっても、やっていることは同じ
• 文脈から値を取り出す ⇒ 関数を適用する ⇒ 元の文脈の中に値を返す
Function
(+1)
Int
Optional
IntInt
Int
Array
Int
IntInt
Int
Int
Optional
IntInt
Int
Array
Int
Int
Int
Int
Function
(+1)
文脈から値を取り出す 値に関数を適用 値を元の文脈の中に返す
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
ちょっと待って、この処理は汎用化できないか?
46
Value(値)
 パターンが見えてきた!Protocolとして定義して、文脈ご
とに拡張する?
Function
(+1)
Int
Optional
IntInt
Int
Array
Int
IntIntInt
Int
Optional
IntInt
Int
Array
Int
IntInt
Int
Function
(+1)
文脈から値を取り出す 値に関数を適用 値を元の文脈の中に返す
コード引用:
https://gist.github.com/mbrandonw/42651182eddf53ca3991
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
ちょっと待って、この処理は汎用化できないか?
47
Value(値)
 パターンが見えてきた!Protocolとして定義して、文脈ご
とに拡張する?
Function
(+1)
Int
Optional
IntInt
Int
Array
Int
IntIntInt
Int
Optional
IntInt
Int
Array
Int
IntInt
Int
Function
(+1)
文脈から値を取り出す 値に関数を適用 値を元の文脈の中に返す
コード引用:
https://gist.github.com/mbrandonw/42651182eddf53ca3991
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
ちょっと待って、この処理は汎用化できないか?
48
Value(値)
 パターンが見えてきた!Protocolとして定義して、文脈ご
とに拡張する?
Function
(+1)
Int
Optional
IntInt
Int
Array
Int
IntIntInt
Int
Optional
IntInt
Int
Array
Int
IntInt
Int
Function
(+1)
文脈から値を取り出す 値に関数を適用 値を元の文脈の中に返す
Functor
• このように、中の値に対して関数を適用する手段(fmap
関数)を提供する文脈を表すデータ型をHaskellでは
Functorと言う
• Swiftではmap関数として提供される。
• つまり、map関数を持っているデータ型はFunctorと言え
る
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
これは、発想の逆転?
49
Value(値)
 Functor型の導入によって文脈のことは気にせずに関数の再利用
ができる
• FunctorはOOPにはない、文脈のデータ型
• fmap関数は文脈の制御を一般化した関数
Function
(+1)
Int
Optional
IntInt
Int
Array
Int
IntIntInt
Int
Optional
IntInt
Int
Array
Int
IntInt
Int
Function
(+1)
文脈から値を取り出す 値に関数を適用 値を元の文脈の中に返す
Function
(+1)
Functor
fmap()
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
これは、発想の逆転?
50
Value(値)
 Functor型の導入によって文脈のことは気にせずに関数の再利用
ができる
• FunctorはOOPにはない、文脈のデータ型
• fmap関数は文脈の制御を一般化した関数
Function
(+1)
Int
Optional
IntInt
Int
Array
Int
IntIntInt
Int
Optional
IntInt
Int
Array
Int
IntInt
Int
Function
(+1)
文脈から値を取り出す 値に関数を適用 値を元の文脈の中に返す
Function
(+1)
Functor
fmap()
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Functor導入の価値
51
Value(値)
 Functor型の導入によって、
• if/forなどの制御文の記述が不要になる
• コードが簡潔になる
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Functor導入の価値
52
Value(値)
 Functor型の導入によって、
• if/forなどの制御文の記述が不要になる
• コードが簡潔になる
• 関数の繋ぎが楽にできる
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
しかし、この場合はどうするか?
 箱(文脈)の中の値に対して適用する関数がさらに文脈のある値
を返すならどうなるか?
• 例えば、Intを引数にもらって、Arrayを返す関数を連続して繋げば?
53
Int
(3)
Function
(tripleValue) Function
(tripleValue)
配列の[3,3,3]が次
の関数の引数とな
る
?
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
しかし、この場合はどうするか?
 箱(文脈)の中の値に対して適用する関数がさらに文脈のある値
を返すならどうなるか?
• 例えば、Intを引数にもらって、Arrayを返す関数を連続して繋げば?
54
1回目は普通に成功
2回目も成功するが、返り値は
2重配列になっている!
3回目はさすがに失敗!!
引数の型が違うと怒られる!
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
しかし、この場合はどうするか?
 箱(文脈)の中の値に対して適用する関数がさらに文脈のある値
を返すならどうなるか?
• 例えば、Intを引数にもらって、Arrayを返す関数を連続して繋げば?
55
Int
(3)
Function
(tripleValue) Function
(tripleValue)
Int
Int
Int
Array
Array
今、この状態!
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
しかし、この場合はどうするか?
 箱(文脈)の中の値に対して適用する関数がさらに文脈のある値
を返すならどうなるか?
• 例えば、Intを引数にもらって、Arrayを返す関数を連続して繋げば?
56
Int
(3)
Function
(tripleValue) Function
(tripleValue)
Int
Int
Int
Array
この状態になれば
OK!
Int
Int
Int
Int
Int
Int
Int
Int
Int
Array
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
これは他の文脈でも同じことが言える!
 先ほどの、Optionalを返す関数を連続してつなげると、
Optionalの中にOptionalが入ってしまう。
57
Function
(/)
Int
OptionalInt
(20)
Function
(/)
Int
(2)
Int
Optional
Optional
これじゃあ、
繋げない!
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
これは他の文脈でも同じことが言える!
 先ほどの、Optionalを返す関数を連続してつなげると、
Optionalの中にOptionalが入ってしまう。
58
Function
(/)
Int
OptionalInt
(20)
Function
(/)
Int
(2)
Int
Optional
この状態になれば
OK!
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Monad
Funtor
もう一つのパターンが見えてきた!
 fmapを使って関数を適用するけど、その関数の返り値が文脈を
持っている場合は、それを外して返す
• 余計な文脈の重複を避ける処理を追加したパターン ⇒ これがモナド!
59
Function
(/)
Int
文脈
Int
Int
文脈
文脈から値を取り出す 値に関数を適用 値を元の文脈の中に返す
文脈
Int
文脈
文脈
Int
文脈
Functor + α
==
Functorの強化版
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
MonadのProtocol定義
60
Value(値)
 Haskellの定義を参考にSwiftのProtocolとして定義したら以下の
ような感じ
• MonadがFunctorの拡張であることがわかる
コード引用:
https://gist.github.com/mbrandonw/42651182eddf53ca3991
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
MonadのProtocol定義
61
Value(値)
 Haskellの定義を参考にSwiftのProtocolとして定義したら以下の
ような感じ
• MonadがFunctorの拡張であることがわかる
Monad
• 文脈を意識せず、連続した関数の適用が可能な文脈を表
すデータ型
• SwiftではflatMap関数として提供される。
• つまり、flatMap関数を持っているデータ型はMonadと言
える
コード引用:
https://gist.github.com/mbrandonw/42651182eddf53ca3991
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
flatMapを使った場合のコード
62
1回目は普通に成功
2回目も成功するが、返り値は
2十配列になっている!
文脈が深くならず、関数を連
鎖させることができる
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
flatMapを使った場合のコード
63
1回目は普通に成功
2回目も成功するが、返り値は
2十配列になっている!
flapMapを使っているなら、
あなたはMonadを
使っているんですよ〜!
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
で、Monadは何か?それは必要か?
 Functor、(Applicative Functor、)Monadは
• FPで関数を文脈を意識せずに繋げるためのデザインパターン
• OOPではifやforループを用いて、プログラムの処理の一部として記述するものを、データ型ご
とに事前に実装したもの
• すごく簡単に言うと、
 Functorはmapを使って関数を渡せば、都合よく実行してくれるデータ型の総称
 MonadはflatMapを使って関数を渡せば、都合よく実行してくれるデータ型の総称
• 使うのは簡単、作るには本文書の内容の他に、「Functor則」、「Monad則」というルールを
守る必要がある
 しかし、SwiftにMonad(able?)というProtocolはない
• 「SwiftはFPじゃないよ。FPの特徴を持っているだけ!」という声も。
 どこまで純粋な関数型プログラミングにしたいか?
• そこに何の意味があるか?
64
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
モナドはブリトー?
65
判断はお任せ!
(観点による)
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
Why Monad? == Why FP?
 Immutableでより安全なコードが書ける
• コンパイル時の最適化によるパフォーマンス向上
 関数を作成し、それらを繋げるだけでコードが書ける
• 複雑なものを複数の小さい関数に分けて対応できる
 Functor、 (Applicative Functor、) Monadなどの概念を理解し、
コードに適用することでより簡潔なコードが書ける
• これらの概念を理解できなくても、map、flatMap、reduceなど、FPから由来するメ
ソッドを適切に使うとコードをより簡潔に記述できる
 参照透過性によって単体テストのためのコードがより簡単になる
• ただし、コードを適切に書いた場合のみ!
66
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
実際には、SwiftでのFP適用には課題がある!
 Swiftが依存するCocoa/CocoaTouchはOOPベースのフレーム
ワーク
• OOPを完全に排除し、純粋な関数型プログラミングを行うのは不可能
• SwiftにFPを採用するには、OOPとの共存の方法を考える必要がある
 FPは難しい
• FPの経験者・有識者が圧倒的に少ないのが現状
• 実際どうかは置いといて、FPは難しいという印象が広がっている
• FPに基づいた適切な設計には脳内改革が必要。しかし、今までのOOPの知識
と経験がそれを邪魔する
• あなたが頑張って書いたコードはFPを知らない同僚の開発者には理解できな
い⇒メンテできないコードの誕生
67
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
現段階の結論:FP @ Swift?
 アップルはFunctionalの「F」も言っていない。
• つまり、ただ開発者達が勝手に思い込みで先走っている可能性もある
• しかし、時代がFPの流行を迎えているのは事実
 個人的な姿勢
• FPで色々なチャレンジを行い、学習する。時代に遅れをとらないように頑張る
 開発チームの一員としての姿勢
• 個人が勝手にFPの手法を乱用しない
• コーディング規約と設計のガイドラインを提示して品質を均一化する
• チームメンバーの学習の機会を設け、徐々にスフトする仕組みを作る
 結論:前向きな様子見
68
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
開発チームとFPとの付き合い方(案)
 iOS、Swiftを意識した、現段階での現実的な対応は恐らく下記の
通り
• 一部のプラクティスは先行的に導入
 Value Typeの活用
 できるだけ副作用のない設計を心がける
 map、flatMapなどのメソッドを列挙型の単純なメソッドとしての活用
 Functor、Applicative、Monadoなど、FPの概念、記法を理解する必要があるものの活
用はまだ考慮しない
• 今後の準備
 開発メンバーの教育をしながらFPの活用事例やプラクティスがより広がることを待つ
 先ずは社内の小規模のプロジェクトから始め、徐々に広げる
 フレームワークの作成など、多数のアプリから共有されるようなものを作成する際には
内部設計として採用を考慮する
69
Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
リソース
70
他に、Githubにて、SwiftとMonadで検索!
Swiftで説明する「モナド」:Swiftにおける関数型プログラミングの使い方

More Related Content

Swiftで説明する「モナド」:Swiftにおける関数型プログラミングの使い方

  • 1. OOP(Swift)で説明するMonad Roy Kim (金 成哲) NCデザイン&コンサルティング株式会社 Swiftで、Functional Prgrammingをどう適用するか?
  • 2. 入る前に 2Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
  • 3. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. Who am I?  金 成哲 (Roy S. Kim) • @royskimJP • [email protected] • UXデザイナー、ITコンサルタント、exエンジニア  Work @ NCデザイン&コンサルティング株式会社 • 2011年3月に創業 • 東京4人、関西3人の体制 • 在宅勤務 & コーワーキングスペース • 企業向けのアプリ開発・UXデザイン • サービスデザイン → UX/UIデザイン → 実装 → 運用・改善までを支援 3
  • 4. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. Swift 4 >100
  • 5. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. Haskell 5 >30
  • 6. 入りながら なぜ、モナド?なぜ、FP? 6Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
  • 7. 入りながら なぜ、モナド?なぜ、FP? 7Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. 関数型プログラミング (Functional Programming) の略
  • 8. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. モナド(Monad)とは?  Wikipediaの説明 • 圏論(けんろん)に基づいた概念  数学の一分野である圏論において、モナド(英語: monad)あるいはトリプル (英語: triple)とは(自己)関手と2つの自然変換の三つ組である。モナドは随伴 関手の理論で使われ、半順序集合上の閉包作用素を任意の圏の上へ一般化する。モ ナドという名前は、対応する圏を一般化するというモナドの動作に注目して、ソー ンダース・マックレーンが哲学用語である「モナド」を借用した。 • 関数型プログラミングにおいての説明  モナド(monad)は計算を表現する構造であり、計算ステップの列からなる。つま り、型がモナド構造をもつというのは、命令を繋げるやり方、言い換えるとその型 をもつ関数をネストさせる規則が定まっていることをいう。これはプログラマがパ イプラインを作ることを可能にする。パイプラインでは入力データを1ステップず つ処理するが、モナドは各アクションに追加の処理規則を上乗せすることができる 8
  • 9. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. モナド(Monad)とは?  Wikipediaの説明 • 圏論(けんろん)に基づいた概念  数学の一分野である圏論において、モナド(英語: monad)あるいはトリプル (英語: triple)とは(自己)関手と2つの自然変換の三つ組である。モナドは随伴 関手の理論で使われ、半順序集合上の閉包作用素を任意の圏の上へ一般化する。モ ナドという名前は、対応する圏を一般化するというモナドの動作に注目して、ソー ンダース・マックレーンが哲学用語である「モナド」を借用した。 • 関数型プログラミングにおいての説明  モナド(monad)は計算を表現する構造であり、計算ステップの列からなる。つま り、型がモナド構造をもつというのは、命令を繋げるやり方、言い換えるとその型 をもつ関数をネストさせる規則が定まっていることをいう。これはプログラマがパ イプラインを作ることを可能にする。パイプラインでは入力データを1ステップず つ処理するが、モナドは各アクションに追加の処理規則を上乗せすることができる 9
  • 10. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. モナドはブリトー? 10
  • 11. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. Swiftは、マルチパラダイムランゲージ  Object Oriented Programming (= OOP) • Cocoa TouchはOOPのフレームワークなので、OOPの採用は必須  Protocol Oriented Programming (= POP) • アップルがWWDC2015で披露、これからのSwiftのパラダイムとして強く展開している • オブジェクトの継承よりProtocolの採用によってより柔軟なコードになる(と言ってい る) • これからの正しい設計は;  親クラスを作って継承(X)  プロトコルを作ってそれに準拠した実装(◎)  Value Oriented Programming (= VOP) • Swiftのデータタイプは基本Immutable • ImmutableなValue Typeを使うことでより安全なコードになる(と、アップルが WWDC2015にて言っている) • Classes=more complexity. Values=less complexity 11
  • 12. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. Swiftは関数型プログラミング言語でもあるのか?  Swiftが出たら「関数型プログラミングができる!」とみん な騒いでいるらしい!? • 専門の書籍も出ている(下図を参照) • 「SwiftでFunctional Programming」という題の講演とブログが流行る • FPの手法を採用したサードパーティライブラリーがたくさん出ている 12
  • 13. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. 話を進める前に、関数型プログラミングとは?  関数型プログラミングはコーディングスタイル(パラダイムでは なく、言語の仕様でもない)  つまり、SwiftでFPをする・しないは選択可能なオプション  Functionが値と同等に使える  functionを他のfunctionの引数や戻り値として使うことができる  ソフトウェアをモジュールとして分離して考える  小さいモジュール(関数)の組み合わせで複雑なシステムを構築する  従って、モジュールの独立性と組み合わせの利便性が大事  副作用(Side Effect)を避ける  参照透明性:同じ引数で関数を呼ぶといつも同じ結果が返ってくることを 保証する  不変性を保つ:Swiftでいう、「let」はあるけど、「var」はない 13
  • 14. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. Swift ≒ Haskell !?  Swiftは先述した、関数型プ ログラミング言語としての 要件を満たしている • Function is first class object.  POP、VOPは実はFPの特徴 でもある(と、言える)  そのせいか、Haskellと Swiftの文法の概念的類似性 が半端ない! 14 Swiftet Haskell Protocol Type class Protocol Extension Instanciation of Type class Value Oriented Programming Referencial Transparancy Optional maybe Pattern Matching Pattern Matching guard guard let let typealias type Etc… Etc… 「Swiftって、Haskellのただのぱっくりじゃ ないか?」と思うくらい!
  • 15. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. FPとSwiftとの関係  Swiftに登場に喜ぶFPファン達、時代の流れはFPに? • 「新しい、しかもApple向けの開発で使えるFP言語ができた!嬉しい!」 • 海外のSwift関連媒体・イベントにはほぼ必ずFPの話が出るように! • 「やっとFPとマーケットが巡り合った時代になった!」と喜ぶ(MSの) 人も。 15 https://channel9.msdn.com/Shows/Going+Deep/Bria n-Beckman-Dont-fear-the-Monads Brian Beckman: Don't fear the Monad Monadを楽しそうに説明してくれる。彼は簡単 だと言っているけど、多分、それはかなり主観 的な話。しかし、結構いい参考にはなる。
  • 16. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. 手続き型プログラミング・OOP ハードウェアを意識した世界 操作手順(レジスターやメモーリの操作など)を記述することで問題を解決 関数型プログラミング きれいな数学の世界。 解決方法の記述(関数の繋がり)で問題を解決 プログラミングにおける二つのアプローチ 16 10101000110110110110101101101101110111011010001011 10110111011011010100011011011011010110110110111011 10110100010111011011101101 101010001101101101101011011011011101110110 ボトム アップ トップ ダウン プログラム
  • 17. 図とサンプルコードで見るFPの考え方 17Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
  • 18. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. FPの概念図 18 Int String Function (+) Value(値)  全ては値(Value)  つまり、関数も値 • Objective-Cでは値として使える関数はBlockのみ • Swifitは全てが関数であり、Closureは無名関数 List [ ] Function (*) Function (%) Custom Data Type Bool
  • 19. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. サンプル:値としての関数の使用例 19
  • 20. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. FPの概念図 20 Int (1) Function (+) Value(値)  同じ引数を与えると必ず同じ結果が得られる • 「足し算」という関数に1と2を引数に渡すと必ず3が返ってくる。 • これが「参照透過性がある」ということ。(Referencial Transparancy) Int (2) Int (3) いつやっても、何度 やっても同じ返り値
  • 21. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. FPの概念図 21 Int (1) Function (+) Value(値)  全ては厳格な型システムによって管理される • 例えば、「足し算」は数字型を二つ引数にもらって、計算結果をまた数 字型で返す型を持つ関数 Int (2) Int (3) Int型の足し算を行う関数の型は (Int, Int) -> Int
  • 22. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. FPの概念図 22 Int (1) Function (+) Value(値)  部分適用した関数が作れる • 複数の引数が必要な関数に一部の引数だけを与えると、その引数をデ フォルト値として持つ新しい関数ができる • これは、Swiftでもできるよね? Function (+1) 一つだけの引数を必要とする、新しい値(関数)の出来上がり! これは関数の部分適用による関数のカリー化と言う。 この関数の型は、(Int) -> Int
  • 23. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. FPの概念図 23 Int (2) Function (*) Value(値)  関数をつなぐことでより複雑な処理ができる • これはOOPのMethod Chainingに似ている Function (+1) Int (3) Int (7) Intの6が次の関数 の引数となる。 引数6と関数が持って いる値1を足してその 結果を返す
  • 24. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. サンプル:関数の部分適用と連鎖 24
  • 25. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. Functional Programming FPの概念図 25 Input Function Value(値)  FPはこれらの関数をつなぐことで必要なプログラムを実装 する • 数学的な関数の記述 • どう処理するかではなく、何であるかの記述 Output Function Function
  • 26. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. Real World Functional Programming FPの概念図 26 Input Function Value(値)  しかし、我らの世界はピュアではない! • ピュアな心だけでは生きていけない! • 不純なことにどう対応するか? Output 副作用(Side Effect)の ない、純粋な世界 Function Function 多様に変化する不純な (?)世界
  • 27. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. Real World Functional Programming FPの概念図 27 Input Function Value(値)  汚れ仕事は他人に任せる! • IOアクションという、外部とのやり取りを代行する関数を使う • IOアクションはできるだけ小さく抑える == 不純なものは最小限に! Output 副作用(Side Effect)の ない、純粋な世界 Function Function 多様に変化する不純な (?)世界 IO アクション IO アクション 二つの世界の接点であり、 関門でもあるIOアクション
  • 28. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. アプリ FPを採用したアプリ設計のあるべき姿? 28 iOS SDK Core OS Core Service Media Cocoa Touch Inherited Object ValueFunction Real World Functional Programming Input Function Output Function Function IO アクション IO アクション ValueFunction Conversion Object & ValueObject Object Function Function
  • 29. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. アプリ FPを採用したアプリ設計のあるべき姿? 29 iOS SDK Core OS Core Service Media Cocoa Touch Inherited Object ValueFunction Real World Functional Programming Input Function Output Function Function IO アクション IO アクション ValueFunction Conversion Object & ValueObject Object Function Function 仲介レイヤー • Cocoa Touch、3rd Partyライブラ リーとの連携 • 外部との連携(ネットワーク処理、 ファイルI/O、ユーザー入力の処理な ど) • このレイヤーをできるだけ薄くする のがいい設計(とされている) FP World • 値と関数の型の定義 • 関数の実装 • アプリの機能はここで実装 OOP World
  • 30. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. アプリ しかし課題は残る! 30 iOS SDK Core OS Core Service Media Cocoa Touch Inherited Object ValueFunction ValueFunction Conversion Object & ValueObject Object Function Function  事実上、関数型プログラミングで純粋に 実装するにはCocoa Touchの存在感が大 きすぎる  値をValueとして取り扱うのは難しい • CoreDataも、Realmも、データの表現には Objectを使っている • それらを、FPをするために、都度Value Type に変換するか?(冗談はやめて〜)  ベストプラクティスはまだ定まってない • FPとOOPの二つの世界の境界をどこに置くか、 またその仲介をどうするかの考慮が必要
  • 31. やっと本題 なぜMonad? 31Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.
  • 32. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. ここで復習 32 Value(値)  FPは関数をつなげることでやりたいことを実現する • 関数を繋げる == メソッドチェーン Int (2) Function (*) Function (+1) Int (3) Int (7) Intの6が次の関数 の引数となる。 引数6と関数が持って いる値1を足してその 結果を返す 6
  • 33. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. 関数の再利用 33 Value(値)  FPは関数を定義し、それを組み合わせることで処理を実行 する  (+1)という関数(plusOne)をせっかく作ったので、多様な シーンで活用したい! Function (+1) 使いまくるぜ〜!
  • 34. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved.  しかし、このような場合はどうする? • 例えば、引数がOptionalなら?? 関数を再利用する場合の課題 34 Int (2) Function (/) Function (+1) Int (0) Int (7) 計算できないので Nonが次の関数の 引数となる Optional型をどう処理 するか? Int?
  • 35. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. Function (+1)  しかし、このような場合はどうする? • 例えば、引数がOptionalなら?? 関数を再利用する場合の課題 35 Int (2) Function (/) Int (0) Int (7) 計算できないので Nonが次の関数の 引数となる Optional型をどう処理 するか? Int? If文で対応できる ぜ!
  • 36. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. 関数を再利用する場合の課題 36 Value(値)  このような場合はどうする? • 例えば、引数が配列なら?? Int (2) Function (tripleValue) Function (+1) Int (7) 配列が次の関数の 引数となる 配列をどう処理す るか? [2,2,2,]
  • 37. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. 関数を再利用する場合の課題 37 Value(値)  このような場合はどうする? • 例えば、引数が配列なら?? Int (2) Function (tripleValue) Function (+1) Int (7) 配列が次の関数の 引数となる 配列をどう処理す るか? [2,2,2,] forループ文で 対応できるぜ!
  • 38. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. しかし、これは関数型プログラミングではない 38 Value(値)  やりたいのは関数をつなぐこと  条件分岐やループ文を書いていてはOOPと同じ • (まあ、悪いとは言わないが、FP的ではない!) これらを、 排除したいのだ!
  • 39. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. 何が問題なのか? 39 Value(値)  値だけを取り扱うには問題がない  しかし、値がOptionalの中にあるか、配列の中に格納されていれ ば、そのままでは使えない • OptionalはIntではない、ArrayもIntではない。つまり、データ型が違う! Int Function (+1) Int Optional IntInt Int Array Int型だけ、 受付るよ〜
  • 40. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. ここで文脈、あの有名な「箱」が登場 40 Value(値)  このような値が何かの状態をもっていることを「文脈の中にある」と 表現する  文脈はよく「箱」と比喩される • 多様な文脈が存在するし、自作することもできる Int Int Optional IntInt Int Array • 値のみ • 文脈がないのでこのまま使える • 値が文脈の中にある。 • Optionalは「値があるかもないかもしれない」 という意味の文脈 • 値が文脈の中にある。 • 配列は「値がいくつあるかしれない」という意 味の文脈
  • 41. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. じゃあ、どうするか? 41 Value(値)  なら、文脈の中から値だけ抜き出せばいい!  すると、関数が適用できるよ〜 Int Function (+1) Int Optional IntInt Int Array Int Int Int Int
  • 42. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. じゃあ、どうするか? 42 Value(値)  OOPでif分やforループでやってたのがまさにこれ! • つまり、値がどの文脈に入っているかによって、取り出す方法が異なる Int Function (+1) Int Optional IntInt Int Array Int Int Int Int Ifでやってた! Forループで やってた!
  • 43. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. もっと行儀よくしようぜ! 43 Value(値)  値を文脈の中から取り出して、関数の適用が終わったら、また元 の文脈の中に入れてあげる! • サービス精神旺盛! Function (+1) Int Optional IntInt Int Array Int IntInt Int Int Optional IntInt Int Array Int Int Int Int
  • 44. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. ちょっと待って、この処理は汎用化できないか? 44 Value(値)  文脈は異なっても、やっていることは同じ • 文脈から値を取り出す ⇒ 関数を適用する ⇒ 元の文脈の中に値を返す Function (+1) Int Optional IntInt Int Array Int IntInt Int Int Optional IntInt Int Array Int Int Int Int Function (+1) 文脈から値を取り出す 値に関数を適用 値を元の文脈の中に返す
  • 45. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. ちょっと待って、この処理は汎用化できないか? 45 Value(値)  文脈は異なっても、やっていることは同じ • 文脈から値を取り出す ⇒ 関数を適用する ⇒ 元の文脈の中に値を返す Function (+1) Int Optional IntInt Int Array Int IntInt Int Int Optional IntInt Int Array Int Int Int Int Function (+1) 文脈から値を取り出す 値に関数を適用 値を元の文脈の中に返す
  • 46. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. ちょっと待って、この処理は汎用化できないか? 46 Value(値)  パターンが見えてきた!Protocolとして定義して、文脈ご とに拡張する? Function (+1) Int Optional IntInt Int Array Int IntIntInt Int Optional IntInt Int Array Int IntInt Int Function (+1) 文脈から値を取り出す 値に関数を適用 値を元の文脈の中に返す コード引用: https://gist.github.com/mbrandonw/42651182eddf53ca3991
  • 47. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. ちょっと待って、この処理は汎用化できないか? 47 Value(値)  パターンが見えてきた!Protocolとして定義して、文脈ご とに拡張する? Function (+1) Int Optional IntInt Int Array Int IntIntInt Int Optional IntInt Int Array Int IntInt Int Function (+1) 文脈から値を取り出す 値に関数を適用 値を元の文脈の中に返す コード引用: https://gist.github.com/mbrandonw/42651182eddf53ca3991
  • 48. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. ちょっと待って、この処理は汎用化できないか? 48 Value(値)  パターンが見えてきた!Protocolとして定義して、文脈ご とに拡張する? Function (+1) Int Optional IntInt Int Array Int IntIntInt Int Optional IntInt Int Array Int IntInt Int Function (+1) 文脈から値を取り出す 値に関数を適用 値を元の文脈の中に返す Functor • このように、中の値に対して関数を適用する手段(fmap 関数)を提供する文脈を表すデータ型をHaskellでは Functorと言う • Swiftではmap関数として提供される。 • つまり、map関数を持っているデータ型はFunctorと言え る
  • 49. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. これは、発想の逆転? 49 Value(値)  Functor型の導入によって文脈のことは気にせずに関数の再利用 ができる • FunctorはOOPにはない、文脈のデータ型 • fmap関数は文脈の制御を一般化した関数 Function (+1) Int Optional IntInt Int Array Int IntIntInt Int Optional IntInt Int Array Int IntInt Int Function (+1) 文脈から値を取り出す 値に関数を適用 値を元の文脈の中に返す Function (+1) Functor fmap()
  • 50. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. これは、発想の逆転? 50 Value(値)  Functor型の導入によって文脈のことは気にせずに関数の再利用 ができる • FunctorはOOPにはない、文脈のデータ型 • fmap関数は文脈の制御を一般化した関数 Function (+1) Int Optional IntInt Int Array Int IntIntInt Int Optional IntInt Int Array Int IntInt Int Function (+1) 文脈から値を取り出す 値に関数を適用 値を元の文脈の中に返す Function (+1) Functor fmap()
  • 51. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. Functor導入の価値 51 Value(値)  Functor型の導入によって、 • if/forなどの制御文の記述が不要になる • コードが簡潔になる
  • 52. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. Functor導入の価値 52 Value(値)  Functor型の導入によって、 • if/forなどの制御文の記述が不要になる • コードが簡潔になる • 関数の繋ぎが楽にできる
  • 53. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. しかし、この場合はどうするか?  箱(文脈)の中の値に対して適用する関数がさらに文脈のある値 を返すならどうなるか? • 例えば、Intを引数にもらって、Arrayを返す関数を連続して繋げば? 53 Int (3) Function (tripleValue) Function (tripleValue) 配列の[3,3,3]が次 の関数の引数とな る ?
  • 54. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. しかし、この場合はどうするか?  箱(文脈)の中の値に対して適用する関数がさらに文脈のある値 を返すならどうなるか? • 例えば、Intを引数にもらって、Arrayを返す関数を連続して繋げば? 54 1回目は普通に成功 2回目も成功するが、返り値は 2重配列になっている! 3回目はさすがに失敗!! 引数の型が違うと怒られる!
  • 55. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. しかし、この場合はどうするか?  箱(文脈)の中の値に対して適用する関数がさらに文脈のある値 を返すならどうなるか? • 例えば、Intを引数にもらって、Arrayを返す関数を連続して繋げば? 55 Int (3) Function (tripleValue) Function (tripleValue) Int Int Int Array Array 今、この状態!
  • 56. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. しかし、この場合はどうするか?  箱(文脈)の中の値に対して適用する関数がさらに文脈のある値 を返すならどうなるか? • 例えば、Intを引数にもらって、Arrayを返す関数を連続して繋げば? 56 Int (3) Function (tripleValue) Function (tripleValue) Int Int Int Array この状態になれば OK! Int Int Int Int Int Int Int Int Int Array
  • 57. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. これは他の文脈でも同じことが言える!  先ほどの、Optionalを返す関数を連続してつなげると、 Optionalの中にOptionalが入ってしまう。 57 Function (/) Int OptionalInt (20) Function (/) Int (2) Int Optional Optional これじゃあ、 繋げない!
  • 58. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. これは他の文脈でも同じことが言える!  先ほどの、Optionalを返す関数を連続してつなげると、 Optionalの中にOptionalが入ってしまう。 58 Function (/) Int OptionalInt (20) Function (/) Int (2) Int Optional この状態になれば OK!
  • 59. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. Monad Funtor もう一つのパターンが見えてきた!  fmapを使って関数を適用するけど、その関数の返り値が文脈を 持っている場合は、それを外して返す • 余計な文脈の重複を避ける処理を追加したパターン ⇒ これがモナド! 59 Function (/) Int 文脈 Int Int 文脈 文脈から値を取り出す 値に関数を適用 値を元の文脈の中に返す 文脈 Int 文脈 文脈 Int 文脈 Functor + α == Functorの強化版
  • 60. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. MonadのProtocol定義 60 Value(値)  Haskellの定義を参考にSwiftのProtocolとして定義したら以下の ような感じ • MonadがFunctorの拡張であることがわかる コード引用: https://gist.github.com/mbrandonw/42651182eddf53ca3991
  • 61. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. MonadのProtocol定義 61 Value(値)  Haskellの定義を参考にSwiftのProtocolとして定義したら以下の ような感じ • MonadがFunctorの拡張であることがわかる Monad • 文脈を意識せず、連続した関数の適用が可能な文脈を表 すデータ型 • SwiftではflatMap関数として提供される。 • つまり、flatMap関数を持っているデータ型はMonadと言 える コード引用: https://gist.github.com/mbrandonw/42651182eddf53ca3991
  • 62. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. flatMapを使った場合のコード 62 1回目は普通に成功 2回目も成功するが、返り値は 2十配列になっている! 文脈が深くならず、関数を連 鎖させることができる
  • 63. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. flatMapを使った場合のコード 63 1回目は普通に成功 2回目も成功するが、返り値は 2十配列になっている! flapMapを使っているなら、 あなたはMonadを 使っているんですよ〜!
  • 64. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. で、Monadは何か?それは必要か?  Functor、(Applicative Functor、)Monadは • FPで関数を文脈を意識せずに繋げるためのデザインパターン • OOPではifやforループを用いて、プログラムの処理の一部として記述するものを、データ型ご とに事前に実装したもの • すごく簡単に言うと、  Functorはmapを使って関数を渡せば、都合よく実行してくれるデータ型の総称  MonadはflatMapを使って関数を渡せば、都合よく実行してくれるデータ型の総称 • 使うのは簡単、作るには本文書の内容の他に、「Functor則」、「Monad則」というルールを 守る必要がある  しかし、SwiftにMonad(able?)というProtocolはない • 「SwiftはFPじゃないよ。FPの特徴を持っているだけ!」という声も。  どこまで純粋な関数型プログラミングにしたいか? • そこに何の意味があるか? 64
  • 65. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. モナドはブリトー? 65 判断はお任せ! (観点による)
  • 66. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. Why Monad? == Why FP?  Immutableでより安全なコードが書ける • コンパイル時の最適化によるパフォーマンス向上  関数を作成し、それらを繋げるだけでコードが書ける • 複雑なものを複数の小さい関数に分けて対応できる  Functor、 (Applicative Functor、) Monadなどの概念を理解し、 コードに適用することでより簡潔なコードが書ける • これらの概念を理解できなくても、map、flatMap、reduceなど、FPから由来するメ ソッドを適切に使うとコードをより簡潔に記述できる  参照透過性によって単体テストのためのコードがより簡単になる • ただし、コードを適切に書いた場合のみ! 66
  • 67. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. 実際には、SwiftでのFP適用には課題がある!  Swiftが依存するCocoa/CocoaTouchはOOPベースのフレーム ワーク • OOPを完全に排除し、純粋な関数型プログラミングを行うのは不可能 • SwiftにFPを採用するには、OOPとの共存の方法を考える必要がある  FPは難しい • FPの経験者・有識者が圧倒的に少ないのが現状 • 実際どうかは置いといて、FPは難しいという印象が広がっている • FPに基づいた適切な設計には脳内改革が必要。しかし、今までのOOPの知識 と経験がそれを邪魔する • あなたが頑張って書いたコードはFPを知らない同僚の開発者には理解できな い⇒メンテできないコードの誕生 67
  • 68. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. 現段階の結論:FP @ Swift?  アップルはFunctionalの「F」も言っていない。 • つまり、ただ開発者達が勝手に思い込みで先走っている可能性もある • しかし、時代がFPの流行を迎えているのは事実  個人的な姿勢 • FPで色々なチャレンジを行い、学習する。時代に遅れをとらないように頑張る  開発チームの一員としての姿勢 • 個人が勝手にFPの手法を乱用しない • コーディング規約と設計のガイドラインを提示して品質を均一化する • チームメンバーの学習の機会を設け、徐々にスフトする仕組みを作る  結論:前向きな様子見 68
  • 69. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. 開発チームとFPとの付き合い方(案)  iOS、Swiftを意識した、現段階での現実的な対応は恐らく下記の 通り • 一部のプラクティスは先行的に導入  Value Typeの活用  できるだけ副作用のない設計を心がける  map、flatMapなどのメソッドを列挙型の単純なメソッドとしての活用  Functor、Applicative、Monadoなど、FPの概念、記法を理解する必要があるものの活 用はまだ考慮しない • 今後の準備  開発メンバーの教育をしながらFPの活用事例やプラクティスがより広がることを待つ  先ずは社内の小規模のプロジェクトから始め、徐々に広げる  フレームワークの作成など、多数のアプリから共有されるようなものを作成する際には 内部設計として採用を考慮する 69
  • 70. Copyright ©2014, NC Design & Consulting Co., Ltd. All rights reserved. リソース 70 他に、Githubにて、SwiftとMonadで検索!