Cats は Scala プログラミング言語で関数型プログラミングを
するための抽象化を提供するライブラリ
Cats is a library to provide abstraction
for functional programming in
the Scala programming language.
software doesn’t exist in a vacuum
水、酸素、光、土壌など
• water
• oxygen
• light
• soil (nutrients, pH)
software doesn’t exist in a vacuum
継続的にメンテ(進化)するための開発リソース、セオリー、
コミュニティ、周辺プラグイン、ドキュメンテーション
• development resource to
maintain/evolve the system
• underlying theory
• user community
• surrounding plugins/libraries
• documentation
60 contributors + 547 pull requests in an
year.
コントリビュータは色んな所から集まってきてる
pull req も一年で 547 本と活発
see also Principles for Modular, Functional,
Approachable Libraries (video, slides)
goals
関数型、安全、高速、ドキュメントが整備されている、
モジュラー、慣用的、実用的、協調、友好的
•Functional
•Safe
•Fast
•Documented
•Modular
•Idiomatic
•Pragmatic
•Collaborative
•Welcoming
see also Principles for Modular, Functional,
Approachable Libraries (video, slides)
goals
Scala で関数型プログラムをおこなう障壁を取り除く
“Remove barriers to doing functional programming in
Scala.”
see also Principles for Modular, Functional,
Approachable Libraries (video, slides)
barriers
技術的な障壁: 複雑さ、職場での障壁: 未知への恐怖、
社会的な障壁: 「これは僕のためのものじゃない」
• technical barriers: complexity (e.g. typeclass is not
first class)
• barriers at work: fear of the unknown (e.g.
performance concerns)
• social barriers: “This is not for me” (e.g. imposter
syndrome and delayed feelings of mastery)
see also Principles for Modular, Functional,
Approachable Libraries (video, slides)
we should
安定した長期的で協力的なコミュニティを促進するために、
新境地を開拓しつつ、高品質なライブラリを提供する
• be willing to break new ground (e.g. build-your-own-
runtime)
• provide high-quality libraries (e.g. documentation,
benchmarks)
• foster a stable, long-term, supportive community
• model good technical and social practices
• reach out and welcome newcomers
• acknowledge the limits of our own knowledge
• provide opportunities for new work
• accept responsibility for education and codes of
conduct
see also Constraints Liberate, Liberties
Constrain (video)
Delphi にプリンタドライバが無かったので直に通信していた
プリンタを変えると使えないプログラムになった
see also Constraints Liberate, Liberties
Constrain (video)
一度中間値を生成して、そこからプリンタに出力するべき
see also Constraints Liberate, Liberties
Constrain (video)
別の例としてはマインクラフトの爆発物
複数使うことでより強力な爆発を起こすことができる
see also Constraints Liberate, Liberties
Constrain (video)
一度こうなってしまうと合成しようが無い
副作用のメンタルイメージとなる
see also Constraints Liberate, Liberties
Constrain (video)
よくある2 つの間違いは早すぎる具現化、
合成可能性を設計段階で考慮しないこと
• concretizing too early
• not designing for compositionality
mistakes we make
see also Constraints Liberate, Liberties
Constrain (video)
具象的なシグネチャ
42億 * 42億通りの実装
def foo(a: Int): Int
see also Constraints Liberate, Liberties
Constrain (video)
型を変えることを許すことで、型を抽象化できる
def foo[A](a: A): A
see also Constraints Liberate, Liberties
Constrain (video)
あるレイヤーでの制約は別のレイヤーでの自由と力になる
a constraint at one level leads to
freedom and power at another level.
finite set and arrow
有限集合と射
これは射の内部図式
internal diagram of an arrow
finite set and arrow
ドメインとコドメイン
有限集合の射は Scala では関数として書ける
val favoriteBreakfast: Person => Breakfast = {
case John => Eggs
case Mary => Coffee
case Sam => Coffee
}
domain codomain
finite set and arrow
これも射の内部図式
Sam が片想いになってる
internal diagram of another arrow
finite set and arrow
ドメインとコドメインが同一の対象の射を自己準同型射と呼ぶ
val favoritePerson: Person => Person = {
case John => Mary
case Mary => John
case Sam => Sam
}
endomorphism: An arrow in which the domain and
codomain are the same object.
finite set and arrow
恒等射: ドメインとコドメインが同一の集合 A で、かつ A 内
の全ての a において f(a) = a であるもの
identity arrow, 1A: An arrow, in which the domain
and codomain are the same set A, and for each of a
in A, f(a) = a
scala> identity(John)
res0: John.type = John
finite set and arrow
これまで見た射の外部図式
external diagrams of the arrows
finite set and arrow
f ∘ g は「f マル g」、または「f と g の合成射」と読む
composition of arrows
“f following g”, or “f of g”
• objects: A, B, C
• arrows: f: A B
• identity arrows: 1A: A A
• composition of arrows
category
圏は対象、射、恒等射、射の合成から構成される
これらのデータは単位元律と結合律を満たす必要がある
• left identity law: If 1A: A A, g: A B, then g ∘ 1A = g
• right identity law: If f: A B, 1B: B B, then 1A ∘ f = f
• associative law: If f: A B, g: B C, h: C D, then
h ∘ (g ∘ f) = (h ∘ g) ∘ f
laws
genericity
「抽象」という言葉を正確に定義できる
圏論から得られる概念にのみよる定義を抽象とする
cat theory gives us tool to think in generic
terms, and precise meaning to “abstract.”
abstract (in cat theory):
The definition uses only of the category
theoric notions, rather than some
additional information about about the
objects and arrows.
genericity
同型射は抽象概念の一例
逆射 g が定義できる射 f は同型射。A と B は同型。
cat theory gives us tool to think in generic
terms, and precise meaning to “abstract.”
abstract (in cat theory): uses only
category theoric notions. for example:
isomorphism: an arrow f: A ⇒ B is called
an isomorphism, if there is an arrow
g: B ⇒ A, for which
g ∘ f = 1A and f ∘ g = 1B
universal mapping property (UMP)
普遍写像性 (UMP; 普遍性)
ある図式があるとき、別の図式を可換とする一意な x がある
given a diagram abc, there exists a unique
x that makes another diagram xyz
commute.
universal mapping property (UMP)
積の一意性: 任意の圏 C において、上の図が可換となる
一意の射 u: X ⇒ P が存在する。
uniqueness of products
Given any category C, there exists a unique
u: X ⇒ P, making the diagram commute.
universal mapping property (UMP)
自由モノイド: 任意のモノイド N と任意の関数 f があるとき、
一意の準同型写像が存在する。
uniqueness of free monoids
Given any monoid N and any function f there exists a unique
monoid homomorphism f_hom: M(X) ⇒ N.
f_hom(x • y) = f_hom(x) •’ f_hom(y), and f_hom(e) = e’
monads
どの 2項演算の上に join が実装されているかが、
そのモナドの意味論を決定する
Both datatypes can crunch the self-similar
structure into a flat one.
What binary operation the flattening is
implemented over determines the
semantics of a monad.
Scala lets you abstract over a monadic datatype
モナディックなデータ型に関して抽象なコードを書ける
trait UserServices[F[_]] { this: UserRepos[F] =>
def userService: UserService = new UserService
class UserService {
import example.MonadSyntax._
def isFriends(user1: Long, user2: Long): F[Boolean] =
actM[F, Boolean] {
val a = userRepo.followers(user1).next
val b = userRepo.followers(user2).next
a.exists(_.id == user2) && b.exists(_.id == user1)
}
}
}
scala> val testService = new TestUserRepos with
UserServices[Id] {}
testService: TestUserRepos with UserServices[cats.Id] = ..
Scala lets you abstract over a monadic datatype
例えば、ここでは XorT[Future, Error, ?] を渡している
..
scala> val testService = new TestUserRepos with
UserServices[Id] {}
testService: TestUserRepos with UserServices[cats.Id] = ..
scala> val service1 = {
import ExecutionContext.Implicits._
new UserRepos1 with UserServices[XorT[Future, Error, ?]] {}
}
service1: UserRepos1 with
UserServices[[γ]cats.data.XorT[scala.concurrent.Future,Error,γ]] =
$anon$1@ff10590