SlideShare a Scribd company logo
Scala 初心者が Hom 函手を Scala で考えてみた
Pre-ScalaMatsuri 2020
高瀬 和之
@Guvalif
>=> 自己紹介
- 名前: 高瀬 和之 (たかせ かずゆき)
- 所属: Chatwork 株式会社 @大阪
- 専門:
- フロントエンド開発
(React / Redux / TypeScript)
- ティーチング
(アルゴリズム / 機械学習 / 数学
/ 組み込みシステム)
- ひとこと:
- Scala のイベントは初めてです 💪
2
>=> アジェンダ
1. ことの発端
2. そもそも函手とは?
3. Hom 函手
4. Scala での実装例
3
01ことの発端
>=> ある日のひとまく
Scala ガチ勢の H 氏 < Haskell 書けるらしいじゃん? Scala もいけるっしょ 💪
たかせ < えっ?
~ 数週間後 ~
- 私に送られてきたのは…
- State Monad ゴリゴリで,
- for 式をいい感じに駆使していて,
- Files changed が 18 くらいある,
- そんな Pull-Request 😇🎉
5
>=> とはいえ…
- 意外とがんばれば読める
- for 式 ⇒ Haskell の do 構文
- Monad ⇒ Haskell の屋台骨
- case class ⇒ Haskell の Record っぽさ
- trait ⇒ Haskell の型クラスっぽさ
- etc...
かくして、”Do Haskell for Scala” という標語が、生まれたとかなんとか…
(※フロントエンド開発メンバーとの日常会話にて)
6
>=> 問題点 🙅‍♂
- なんとなく読める ≠ 使いこなせる
- Scala の言語仕様をきちんと理解した上で、モナモナできるようになりたい!
というわけで…
1. まずはファンクタファンクタできるように、型クラス周りの仕様を知る
2. 何か適当な Functor を実装してみる
こうして私は Scala に入門しました 🚪
7
02そもそも函手とは?
~ 圏論への招待 ~
>=> 圏論ことはじめ (1):対象と射
- 圏論の材料
- 対象 ⇒ 点
- 射 ⇒ 点から点を結ぶ矢印 (点と点の関連性を表す)
- ここまでの事実 ⇒ なんか有向グラフっぽい
9
>=> 圏論ことはじめ (2):圏の例
- しりとりの圏 (対象:ひらがな,射:単語)
10
- 型と関数の圏 (対象:型,射:関数)
り ご ら ぱ り
りんご ごりら らっぱ ぱせり
String Int
Boolean
length
isEven
isCamelCase
>=> 圏論ことはじめ (3):函手 / Functor
- ある圏から、グラフ構造を全て抜き出す
- 別の圏にて、グラフ構造が一致する箇所に対応づける
- 対象と対象の対応関係,および射と射の対応関係,その2つ組と考えてもよい
(※実際には公理を満たすように,かつ実用的に必要な性質を盛り込んで考えます)
11
圏 D圏 C
03Hom 函手
>=> Hom 函手ことはじめ (1):Hom 集合
- 圏論では、ある対象 ● から別の対象 ● へ、複数の射が存在してもよい
- すなわち、射の集合を考えることができる ⇒ Hom 集合と呼ぶ
- 対象 ● から対象 ● に関する Hom 集合 ⇒ Hom(●, ●) と表す
- 下図の場合:
- Hom(●, ●) = { a, b, c, d, e }
- Hom(●, ●) = ∅
13
a
e
d
b
c
>=> Hom 函手ことはじめ (2):舞台を集合の圏へ
- 圏 C で何か1つ対象を固定する (今回は X)
- 固定した対象と、圏 C の任意の対象に関して、Hom 集合を取る
14
X
A
D C
B
圏 C 集合の圏
Hom(X, A)
Hom(X, B)
Hom(X, C)
※Hom(X, D) は空集合
>=> Hom 函手ことはじめ (3):Hom 集合の間に射が存在する条件
- 対象 X から対象 A への任意の射 a
- 対象 X から対象 B へのある射 b
- これらに対して、b = f ∘ a を満たす射 f が存在すること
(※ b を使って X から B へ向かうことと、a と f を使って X から B へ向かうことが等しくなる,の意)
15
X
B
A
圏 C 集合の圏
Hom(X, A)
Hom(X, B)
∀a
∃b
∃f, b = f ∘ a
f ∘ _
>=> Hom 函手ことはじめ (4):共変 Hom 函手
- 共変 Hom 函手とは:
- 任意の圏から集合の圏への函手であって,
- 対象 * を対象 Hom(X, *) へ移し,
- (制約を満たす) 射 f を射 f ∘ _ へ移す,そんな函手
16
X
B
A
圏 C 集合の圏
Hom(X, A)
Hom(X, B)
∀a
∃b
∃f, b = f ∘ a
f ∘ _
04Scala での実装例
>=> 共変 Hom 函手 in Scala
- 型と関数の圏をベースに、Scala 圏を考えると:
- * → Hom(X, *) なる対象の対応は、カインド X => * として表現できる
(※厳密には、指数対象というものを考えて、Hom 集合を Scala 圏に埋め込むとそうなります)
- f → f ∘ _ なる射の対応は、高階関数 f => f compose _ として表現できる
18
X
B
A
Scala 圏 Scala 圏
X => A
X => B
∀a
∃b
∃f, b = f compose a
f compose _
>=> 実際にやってみた
// F[_] が対象の対応関係を,map が射の対応関係を表す
trait EndoFunctor[F[_]] {
def map[A, B](f: A => B): F[A] => F[B]
}
type X = Unit // 固定する型は何でも良いが、今回は Unit 型
type Xto[Y] = X => Y // Hom 函手における、対象の対応関係
implicit val homFunctor = new EndoFunctor[Xto] {
def map[A, B](f: A => B): Xto[A] => Xto[B] = // Hom 函手における、射の対応関係
f compose _
}
// 任意の函手の実装を用いて、射を相手先の圏へ移す(※といいつつ Scala 圏には閉じてるので、Endo = 自己)
def map[F[_], A, B](f: A => B)(implicit functor: EndoFunctor[F]): F[A] => F[B] =
functor.map(f)
19
>=> 実際につかってみた
val f: Int => String = x => s"String($x)" // Int と String を結ぶ射をピックアップ
val Fa: Xto[Int] = x => 0 // Hom(X, Int) から、要素をピックアップ
// 1. Hom(X, Int) の要素 Fa
// 2. Hom 集合を結ぶ射 map(f)
// これらから、Hom(X, String) の要素 Fb を導出
val Fb: Xto[String] = map(f).apply(Fa)
println(Fb(())) // String(0) と表示される
20
- 実装してみての感想:
- 高階カインドは、やはりあると表現力が高い 🎉
- implicit parameter は、auto capturing default parameter だと思った 🤔
- 本当は map(f).apply(Fa) の部分を、map(f)(Fa) と書けたらかっちょよい
ちなみに…
Chatwork では、社内勉強会で圏論なんかも取り扱っているらしいですよ 👍

More Related Content

PDF
Scala 初心者が米田の補題を Scala で考えてみた
PDF
技術者が知るべき Gröbner 基底
KEY
ラムダ計算入門
PPTX
PySparkによるジョブを、より速く、よりスケーラブルに実行するための最善の方法 ※講演は翻訳資料にて行います。 - Getting the Best...
PDF
圏論のモナドとHaskellのモナド
PDF
Rolling Hashを殺す話
PDF
F#入門 ~関数プログラミングとは何か~
Scala 初心者が米田の補題を Scala で考えてみた
技術者が知るべき Gröbner 基底
ラムダ計算入門
PySparkによるジョブを、より速く、よりスケーラブルに実行するための最善の方法 ※講演は翻訳資料にて行います。 - Getting the Best...
圏論のモナドとHaskellのモナド
Rolling Hashを殺す話
F#入門 ~関数プログラミングとは何か~

What's hot (20)

PDF
圏とHaskellの型
PDF
数学プログラムを Haskell で書くべき 6 の理由
PDF
計算可能実数とは
PDF
明日使えないすごいビット演算
PPT
Gurobi python
PDF
Union find(素集合データ構造)
PDF
勉強か?趣味か?人生か?―プログラミングコンテストとは
PPTX
数学カフェAdvent calendar2017 12_18〜圏論に於ける準同型定理〜
PDF
abc032
PDF
統計的学習の基礎6章前半 #カステラ本
PDF
Boostのあるプログラミング生活
PDF
AtCoder Regular Contest 022 解説
PDF
組合せ最適化入門:線形計画から整数計画まで
PDF
SAT/SMTソルバの仕組み
PDF
とぽろじー入門(画像なし版)
PPTX
純粋関数型アルゴリズム入門
PDF
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
PDF
Pythonによる黒魔術入門
PDF
楕円曲線入門 トーラスと楕円曲線のつながり
PDF
定理証明支援系Coqについて
圏とHaskellの型
数学プログラムを Haskell で書くべき 6 の理由
計算可能実数とは
明日使えないすごいビット演算
Gurobi python
Union find(素集合データ構造)
勉強か?趣味か?人生か?―プログラミングコンテストとは
数学カフェAdvent calendar2017 12_18〜圏論に於ける準同型定理〜
abc032
統計的学習の基礎6章前半 #カステラ本
Boostのあるプログラミング生活
AtCoder Regular Contest 022 解説
組合せ最適化入門:線形計画から整数計画まで
SAT/SMTソルバの仕組み
とぽろじー入門(画像なし版)
純粋関数型アルゴリズム入門
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonによる黒魔術入門
楕円曲線入門 トーラスと楕円曲線のつながり
定理証明支援系Coqについて
Ad

Similar to Scala 初心者が Hom 函手を Scala で考えてみた (14)

PDF
これから Haskell を書くにあたって
ODP
これから Haskell を書くにあたって
PDF
ScalaプログラマのためのHaskell入門
PDF
GParsの?Actor Model
PDF
do Notation Equivalents in JVM languages: Scala, Kotlin, Clojure
PPTX
F#のコンピュテーション式
KEY
Applicative functor
PDF
Yoneda's lemma tutorial
PDF
これからの「言語」の話をしよう ―― 未来を生きるためのツール
PDF
モナドハンズオン前座
PDF
Freer Monads, More Extensible Effects
PDF
Ekmett勉強会発表資料
KEY
モナドがいっぱい!
PDF
関数型都市忘年会『はじめての函数型プログラミング』
これから Haskell を書くにあたって
これから Haskell を書くにあたって
ScalaプログラマのためのHaskell入門
GParsの?Actor Model
do Notation Equivalents in JVM languages: Scala, Kotlin, Clojure
F#のコンピュテーション式
Applicative functor
Yoneda's lemma tutorial
これからの「言語」の話をしよう ―― 未来を生きるためのツール
モナドハンズオン前座
Freer Monads, More Extensible Effects
Ekmett勉強会発表資料
モナドがいっぱい!
関数型都市忘年会『はじめての函数型プログラミング』
Ad

Scala 初心者が Hom 函手を Scala で考えてみた

  • 1. Scala 初心者が Hom 函手を Scala で考えてみた Pre-ScalaMatsuri 2020 高瀬 和之 @Guvalif
  • 2. >=> 自己紹介 - 名前: 高瀬 和之 (たかせ かずゆき) - 所属: Chatwork 株式会社 @大阪 - 専門: - フロントエンド開発 (React / Redux / TypeScript) - ティーチング (アルゴリズム / 機械学習 / 数学 / 組み込みシステム) - ひとこと: - Scala のイベントは初めてです 💪 2
  • 3. >=> アジェンダ 1. ことの発端 2. そもそも函手とは? 3. Hom 函手 4. Scala での実装例 3
  • 5. >=> ある日のひとまく Scala ガチ勢の H 氏 < Haskell 書けるらしいじゃん? Scala もいけるっしょ 💪 たかせ < えっ? ~ 数週間後 ~ - 私に送られてきたのは… - State Monad ゴリゴリで, - for 式をいい感じに駆使していて, - Files changed が 18 くらいある, - そんな Pull-Request 😇🎉 5
  • 6. >=> とはいえ… - 意外とがんばれば読める - for 式 ⇒ Haskell の do 構文 - Monad ⇒ Haskell の屋台骨 - case class ⇒ Haskell の Record っぽさ - trait ⇒ Haskell の型クラスっぽさ - etc... かくして、”Do Haskell for Scala” という標語が、生まれたとかなんとか… (※フロントエンド開発メンバーとの日常会話にて) 6
  • 7. >=> 問題点 🙅‍♂ - なんとなく読める ≠ 使いこなせる - Scala の言語仕様をきちんと理解した上で、モナモナできるようになりたい! というわけで… 1. まずはファンクタファンクタできるように、型クラス周りの仕様を知る 2. 何か適当な Functor を実装してみる こうして私は Scala に入門しました 🚪 7
  • 9. >=> 圏論ことはじめ (1):対象と射 - 圏論の材料 - 対象 ⇒ 点 - 射 ⇒ 点から点を結ぶ矢印 (点と点の関連性を表す) - ここまでの事実 ⇒ なんか有向グラフっぽい 9
  • 10. >=> 圏論ことはじめ (2):圏の例 - しりとりの圏 (対象:ひらがな,射:単語) 10 - 型と関数の圏 (対象:型,射:関数) り ご ら ぱ り りんご ごりら らっぱ ぱせり String Int Boolean length isEven isCamelCase
  • 11. >=> 圏論ことはじめ (3):函手 / Functor - ある圏から、グラフ構造を全て抜き出す - 別の圏にて、グラフ構造が一致する箇所に対応づける - 対象と対象の対応関係,および射と射の対応関係,その2つ組と考えてもよい (※実際には公理を満たすように,かつ実用的に必要な性質を盛り込んで考えます) 11 圏 D圏 C
  • 13. >=> Hom 函手ことはじめ (1):Hom 集合 - 圏論では、ある対象 ● から別の対象 ● へ、複数の射が存在してもよい - すなわち、射の集合を考えることができる ⇒ Hom 集合と呼ぶ - 対象 ● から対象 ● に関する Hom 集合 ⇒ Hom(●, ●) と表す - 下図の場合: - Hom(●, ●) = { a, b, c, d, e } - Hom(●, ●) = ∅ 13 a e d b c
  • 14. >=> Hom 函手ことはじめ (2):舞台を集合の圏へ - 圏 C で何か1つ対象を固定する (今回は X) - 固定した対象と、圏 C の任意の対象に関して、Hom 集合を取る 14 X A D C B 圏 C 集合の圏 Hom(X, A) Hom(X, B) Hom(X, C) ※Hom(X, D) は空集合
  • 15. >=> Hom 函手ことはじめ (3):Hom 集合の間に射が存在する条件 - 対象 X から対象 A への任意の射 a - 対象 X から対象 B へのある射 b - これらに対して、b = f ∘ a を満たす射 f が存在すること (※ b を使って X から B へ向かうことと、a と f を使って X から B へ向かうことが等しくなる,の意) 15 X B A 圏 C 集合の圏 Hom(X, A) Hom(X, B) ∀a ∃b ∃f, b = f ∘ a f ∘ _
  • 16. >=> Hom 函手ことはじめ (4):共変 Hom 函手 - 共変 Hom 函手とは: - 任意の圏から集合の圏への函手であって, - 対象 * を対象 Hom(X, *) へ移し, - (制約を満たす) 射 f を射 f ∘ _ へ移す,そんな函手 16 X B A 圏 C 集合の圏 Hom(X, A) Hom(X, B) ∀a ∃b ∃f, b = f ∘ a f ∘ _
  • 18. >=> 共変 Hom 函手 in Scala - 型と関数の圏をベースに、Scala 圏を考えると: - * → Hom(X, *) なる対象の対応は、カインド X => * として表現できる (※厳密には、指数対象というものを考えて、Hom 集合を Scala 圏に埋め込むとそうなります) - f → f ∘ _ なる射の対応は、高階関数 f => f compose _ として表現できる 18 X B A Scala 圏 Scala 圏 X => A X => B ∀a ∃b ∃f, b = f compose a f compose _
  • 19. >=> 実際にやってみた // F[_] が対象の対応関係を,map が射の対応関係を表す trait EndoFunctor[F[_]] { def map[A, B](f: A => B): F[A] => F[B] } type X = Unit // 固定する型は何でも良いが、今回は Unit 型 type Xto[Y] = X => Y // Hom 函手における、対象の対応関係 implicit val homFunctor = new EndoFunctor[Xto] { def map[A, B](f: A => B): Xto[A] => Xto[B] = // Hom 函手における、射の対応関係 f compose _ } // 任意の函手の実装を用いて、射を相手先の圏へ移す(※といいつつ Scala 圏には閉じてるので、Endo = 自己) def map[F[_], A, B](f: A => B)(implicit functor: EndoFunctor[F]): F[A] => F[B] = functor.map(f) 19
  • 20. >=> 実際につかってみた val f: Int => String = x => s"String($x)" // Int と String を結ぶ射をピックアップ val Fa: Xto[Int] = x => 0 // Hom(X, Int) から、要素をピックアップ // 1. Hom(X, Int) の要素 Fa // 2. Hom 集合を結ぶ射 map(f) // これらから、Hom(X, String) の要素 Fb を導出 val Fb: Xto[String] = map(f).apply(Fa) println(Fb(())) // String(0) と表示される 20 - 実装してみての感想: - 高階カインドは、やはりあると表現力が高い 🎉 - implicit parameter は、auto capturing default parameter だと思った 🤔 - 本当は map(f).apply(Fa) の部分を、map(f)(Fa) と書けたらかっちょよい