92
圏論と プログラミング 2020/01/25 シンポジウム 「圏論的世界像からはじまる複合知の展望」 Yasuhiro Inami / @inamiy

Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

圏論と プログラミング2020/01/25 シンポジウム 「圏論的世界像からはじまる複合知の展望」

Yasuhiro Inami / @inamiy

Page 2: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

稲見 泰宏 (iOSアプリ開発者・フリーランス)

• 2009-2010 PHP, JavaScript (Web制作)

• 2010-2014 Objective-C, Java (iOSアプリ、サーバーサイド開発)

• 2014- Swift, Haskell (iOS、趣味)

• 2018- 圏論

Page 3: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

2018/09/02 iOSDC 2018 圏論とSwiftへの応用 https://speakerdeck.com/inamiy/iosdc-japan-1

2018/10/16 プログラマのための圏論勉強会 プログラマのためのモナド(圏論) https://speakerdeck.com/inamiy/number-cat4pg

2019/09/06 iOSDC 2019 Swiftと論理 ~そして帰ってきた圏論~ https://speakerdeck.com/inamiy/swift-and-logic-and-category-theory

Page 4: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Q. プログラマーは 「圏論」を学んだ方が良い?🤔

Page 5: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

プログラミング言語の変遷

1990年代の言語 (インターネット普及期、サーバーサイド開発)

• Python (1991)

• Ruby (1995)

• Java (1995)

• JavaScript (1995)

• PHP (1995)

2010年代の言語 (スマートフォン普及期、フロントエンド大規模開発)

• Rust (2010)

• Kotlin (2011)

• TypeScript (2012)

• Swift (2014)

Page 6: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

近年のプログラミング言語に共通していること

•静的型付け言語 + 型推論 •ジェネリクス(多相性) •代数的データ型(直積、直和、パターンマッチング) •モナド(Optional, Result, Future, Observable, etc)

関数型プログラミングの台頭!

Page 7: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Haskell (1990) 近年のモダンな言語は、Haskellの影響を強く受けている

Page 8: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

圏論 (1945) 数学、論理学、物理学、計算機科学など、

ありとあらゆる学問分野で用いられる「矢印」の理論

Page 9: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

プログラマーが圏論を学ぶと嬉しいこと

•プログラミングの基礎理論が学べる

•型付きλ計算 ⇔ 論理学 ⇔ 圏論

•数学の基礎(代数学)、モナドなど

•実務での型計算、設計、抽象化のスキルが上がる

•論文が読めるようになる

•将来の流行を一足先にキャッチアップできる (Effect System等)

Page 10: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

アジェンダ

•圏の定義 •関手 •自然変換 •米田の補題 •随伴 •Kan拡張

•モナド, コモナド •アプリカティブ関手 •Profunctor, Arrow •Optics (Lens) •Recursion Scheme

Page 11: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

圏の定義 Definition of Category

Page 12: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

圏の定義

-- 恒等射 id :: a -> a id a = a

-- 射の合成 (.) :: (b -> c) -> (a -> b) -> (a -> c) f . g = \x -> f (g x)

単位法則 id ∘ f ≅ f ∘ id ≅ f( f ∘ g) ∘ h ≅ f ∘ (g ∘ h)結合法則

Page 13: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

型クラスを使った圏の定義

class Category cat where id :: cat a a (.) :: cat b c -> cat a b -> cat a c

-- 「型」と「関数 (->)」の圏 (Hask) instance Category (->) where id :: (->) a a -- a -> a と同じ id a = a

(.) :: (->) b c -> (->) a b -> (->) a c f . g = \x -> f (g x)

Page 14: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

圏の例:クライスリ圏

-- クライスリ射 newtype Kleisli m a b = Kleisli { runKleisli :: a -> m b }

-- クライスリ圏 instance Monad m => Category (Kleisli m) where id :: (Kleisli m) a a id = Kleisli pure

-- Note: (<=<) と同じ (.) :: (Kleisli m) b c -> (Kleisli m) a b -> (Kleisli m) a c f . g = Kleisli (\x -> runKleisli g x >>= runKleisli f)

Page 15: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

圏の例:レンズ圏

-- レンズ:直積データ構造の getter & setter data Lens a b = Lens (a -> b) (a -> b -> a)

-- レンズ圏 instance Category Lens where id :: Lens a a id = Lens Prelude.id (const Prelude.id)

(.) :: Lens b c -> Lens a b -> Lens a c Lens g1 s1 . Lens g2 s2 = Lens (g1 Prelude.. g2) s3 where s3 a c = s2 a (s1 (g2 a) c)

Page 16: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

関手 Functor

Page 17: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

A f F( f )F(A)

F(B)B

C F(C)

F

C D

g F(g)

g ∘ fF(g ∘ f )

= F(g) ∘ F( f )

Page 18: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

関手

class (Category c, Category d) => Functor' c d f where fmap' :: c a b -> d (f a) (f b)

-- Functor則 -- fmap' id = id -- fmap' (g . h) = fmap' g . fmap' h

-- インスタンス例 instance Functor' (->) (->) Maybe where fmap' _ Nothing = Nothing fmap' f (Just a) = Just (f a)

Page 19: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

自己関手 (Endofunctor)

-- (Endo)Functor == Functor' (->) (->) class Functor f where fmap :: (a -> b) -> f a -> f b

instance Functor Maybe where fmap _ Nothing = Nothing fmap f (Just a) = Just (f a)

Haskell における Functor は、 Hask圏 (射が「->」) における自己関手 (Endofunctor)

Page 20: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

関手圏・自然変換 Functor Category, Natural Transformation

Page 21: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

A

B

F

f

G

F(A) F(B)

G(A) G(B)

F( f )

G( f )

α αA αB

C D関手圏DC

Page 22: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

関手圏と自然変換

newtype f :~> g = NT { unNT :: forall x. f x -> g x }

-- 対象が関手、射が自然変換の関手圏 instance Category (:~>) where id :: a :~> a id = NT Prelude.id

(.) :: (b :~> c) -> (a :~> b) -> (a :~> c) -- 垂直合成 NT f . NT g = NT (f Prelude.. g)

Page 23: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

自然変換の例:多相関数

head' :: List :~> Maybe -- List a -> Maybe a head' = NT $ \case Nil' -> Nothing Cons' a _ -> Just a

length' :: List :~> Const Int -- List a -> Int length' = NT $ \case Nil' -> Const 0 Cons' _ as -> Const $ 1 + getConst (unNT length' as)

Page 24: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

自然同型の例: Maybe a ≅ 1 + a

-- Maybeを構成する各コンストラクタ nothing :: Const () :~> Maybe -- (() -> Maybe a) ≅ Maybe a just :: Identity :~> Maybe -- a -> Maybe a

-- 関手の直和 data (f :+: g) e = InL (f e) | InR (g e)

-- 自然同型:1 + a ≅ Maybe a toMaybe :: (Const () :+: Identity) :~> Maybe -- nothing + just fromMaybe :: Maybe :~> (Const () :+: Identity)

Page 25: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

米田の補題 Yoneda Lemma

Page 26: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

A

B

Hom(A, − )

f

F

Hom(A, A)

Hom(A, B)

F(A)

f…

F(B)

Hom(A, f )= f ∘ −

F( f )

α αA αB

αA ★

idA

……

関手圏SetCC Set

Page 27: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

米田の補題

newtype Yoneda f a = Yoneda { runYoneda :: forall b. (a -> b) -> f b }

instance Functor (Yoneda f) where fmap f m = Yoneda (\k -> runYoneda m (k . f))

-- Yoneda f a ≅ f a liftYoneda :: Functor f => f a -> Yoneda f a lowerYoneda :: Yoneda f a -> f a

Nat(Hom(A, − ), F) ≅ F(A)

F(A) = A のとき、CPS (継続) F(A) = X → A のとき、CPS変換

Page 28: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

米田埋め込み

米田の原理

Hom( − , A) ≅ Hom( − , B) ⟺ A ≅ B

Nat(Hom( − , A), Hom( − , B)) ≅ Hom(A, B)(Hom は充満忠実かつ対象上単射)

Page 29: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

米田の原理の例:型計算

≅ Hom(X × C, AB)

(AB)C ≅ A(B×C)

Hom(X, (AB)C)

≅ Hom((X × C) × B, A)≅ Hom(X × (B × C), A)≅ Hom(X, A(B×C))

A × (B + C) ≅ (A × B) + (A × C)(A × B)C ≅ AC × BC A(B+C) ≅ AB × ACその他、

など

Page 30: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

余米田の補題 (Coyoneda)

data Coyoneda f a where Coyoneda :: (z -> a) -> f z -> Coyoneda f a

instance Functor (Coyoneda f) where fmap f (Coyoneda g v) = Coyoneda (f . g) v

-- Coyoneda f a ≅ f a liftCoyoneda :: f a -> Coyoneda f a lowerCoyoneda :: Functor f => Coyoneda f a -> f a

∫Z

F(Z) × Hom(Z, A) ≅ F(A)

lift時にFunctorが必要ないので 任意の f をCoyoneda関手として扱える

あるZが存在 (Coend, 存在量化)

Page 31: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

共変 Yoneda / Coyoneda

反変 Yoneda / Coyoneda

f' a ≅ ∀b. (b -> a) -> f' b f' a ≅ ∃b. (a -> b, f' b)

f a ≅ ∀b. (a -> b) -> f b f a ≅ ∃b. (b -> a, f b)

Page 32: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

随伴 Adjunction

Page 33: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

F

U

F(A)

B

A

U(B)

≅rightAdjunct

leftAdjunct

D C

Page 34: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

F(A)

B

F

U

A

U(B)

F(U(B)) U(F(A)) ff

F( f )

U( f )

ηA = unitA

εB = counitB

D C

Page 35: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

随伴 (f = 左随伴, u = 右随伴)

class (Functor f, Functor u) => Adjunction f u where unit :: a -> u (f a) counit :: f (u a) -> a leftAdjunct :: (f a -> b) -> a -> u b rightAdjunct :: (a -> u b) -> f a -> b

unit = leftAdjunct id counit = rightAdjunct id leftAdjunct f = fmap f . unit rightAdjunct f = counit . fmap f

-- unit と counit または leftAdjunct と rightAdjunct の実装が必要

Page 36: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

随伴の例:直積 ⊣ 冪 (curry/uncurry)

-- B × ? ⊣ (?)^B instance Adjunction ((,) b) ((->) b) where -- curry leftAdjunct :: ((b, a) -> c) -> a -> b -> c leftAdjunct f a b = f (b, a)

-- uncurry rightAdjunct :: (a -> b -> c) -> (b, a) -> c rightAdjunct f (b, a) = f a b

Hom(A × B, C) ≅ Hom(A, CB)

Page 37: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

随伴の例:クライスリ圏への埋め込み関手 ⊣ 拡張関手

class (Functor' c d f, Functor' d c u) => Adjunction' c d f u where leftAdjunct' :: d (f a) b -> c a (u b) rightAdjunct' :: c a (u b) -> d (f a) b

instance Monad m => Functor' (->) (Kleisli m) Identity where fmap' :: (a -> b) -> Kleisli m (Identity a) (Identity b) fmap' f = Kleisli $ fmap Identity . (pure . f . runIdentity)

instance Monad m => Functor' (Kleisli m) (->) m where fmap' :: Kleisli m a b -> m a -> m b fmap' k = (Prelude.=<<) (runKleisli k)

instance Monad m => Adjunction' (->) (Kleisli m) Identity m where leftAdjunct' :: Kleisli m (Identity a) b -> a -> m b leftAdjunct' k a = runKleisli k (Identity a)

rightAdjunct' :: (a -> m b) -> Kleisli m (Identity a) b rightAdjunct' f = Kleisli $ f . runIdentity

HomCT(A, B) ≅ HomC(A, M(B))

Page 38: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Kan拡張 Kan Extension

Page 39: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Cat

H

A

GRanGH

F

B C

σ

Page 40: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Cat

B CH

ε ε ∘ σG

F ∘ G

(RanGH) ∘ G

σG

σとGの水平合成

Page 41: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Cat

H

GRanGH

σ

A

B

F ∘ G

ε(RanGH) ∘ G

σG

(ε ∘ σG)B

σA

F

F(G(B)) H(B)

F(A) (RanGH)(A)B

A

C

fromRan toRan

toRan :: Functor f => (forall b . f (g b) -> h b) -> f a -> Ran g h a

fromRan :: (forall a . f a -> Ran g h a) -> f (g b) -> h b

Page 42: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

− ∘ G

RanG−

F ∘ G

H

F

RanGH

≅fromRan

toRan

CB CA

Page 43: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Kan拡張 (極限、随伴、米田を含む、全ての概念)

-- 右Kan拡張(極限、右随伴、Yoneda)、F = Hom(a,-) とおく newtype Ran g h a = Ran { runRan :: forall b. (a -> g b) -> h b }

yonedaToRan :: Yoneda f a -> Ran Identity f a ranToYoneda :: Ran Identity f a -> Yoneda f a

adjunctionToCodensity :: Adjunction f g => g (f a) -> Codensity g a codensityToRan :: Codensity g a -> Ran g g a

ranToCodensity :: Ran g g a -> Codensity g a codensityToAdjunction :: Adjunction f g => Codensity g a -> g (f a)

-- 左Kan拡張(余極限、左随伴、Coyoneda) data Lan g h a where Lan ::(g b -> a) -> h b -> Lan g h a

Page 44: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

応用編

Page 45: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

モナド・コモナド Monad, Comonad

Page 46: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

モナド

class Applicative m => Monad m where join :: m (m a) -> m a -- μ: M^2 -> M join x = x >>= id

(>>=) :: m a -> (a -> m b) -> m b m >>= f = join (fmap f m)

return :: a -> m a -- η: 1 -> M return = pure

参考: プログラマのためのモナド(圏論) https://speakerdeck.com/inamiy/number-cat4pg

Page 47: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

随伴から作るモナド (M = UF)

class Adjunction f u => Monad' f u where return' :: a -> u (f a) -- η: 1 -> M join' :: u (f (u (f a))) -> u (f a) -- μ: M^2 -> M

-- 例:f = (s, ?), u = s -> ?, uf = s -> (s, ?) = Stateモナド instance Monad' ((,) s) ((->) s) where return' :: a -> (s -> (s, a)) return’ a s = (s, a) -- == unit

join' :: (s -> (s, (s -> (s, a)))) -> (s -> (s, a)) join' f s = f' s' where (s', f') = f s

Page 48: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

F(C)F

U

C

U(F(C))

ηC

U(F(U(F(C))))

F(U(F(C)))

ϵF(C)

UϵF(C)

D Cモナド(return)

(join)

Page 49: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

コモナド

-- 無限の点集合からなる状態空間と、現在位置を持つイメージ class Functor w => Comonad w where extract :: w a -> a -- 現在位置の状態を取得

-- 現在位置を全パターン分ずらしつつ、状態空間をすべて複製 duplicate :: w a -> w (w a) duplicate = extend id

extend :: (w a -> b) -> w a -> w b extend f = fmap f . duplicate

•インスタンス例: NonEmptyList, Stream, RoseTree, Zipper, Moore •利用例:画像フィルタ、ライフゲームなどの畳み込み演算、React Component

Page 50: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

随伴から作るコモナド (W = FU)

class Adjunction f u => Comonad' f u where extract' :: f (u a) -> a — ε: W -> 1 duplicate' :: f (u a) -> f (u (f (u a))) -- δ: W -> W^2

-- 例:f = (s, ?), u = s -> ?, fu = (s, s -> ?) = Storeコモナド instance Comonad' ((,) s) ((->) s) where extract' :: (s, s -> a) -> a extract' (s, f) = f s -- == counit

duplicate' :: (s, s -> a) -> (s, s -> (s, s -> a)) duplicate' (s, f) = (s, \s -> (s, f))

Page 51: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

F

U

U(F(U(D)))

U(D)

F(U(D))FηU(D)

ηU(D)

D Cコモナド

D

F(U(F(U(D))))

ϵD(extract)

(duplicate)

Page 52: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

-- 例:Storeコモナド と ライフゲーム (セルオートマトン) data Store s a = Store (s -> a) s -- instance of Functor, Comonad, ComonadStore

type Pos = (Int, Int) type Grid = Store Pos Bool

neighbors :: Pos -> [Pos] neighbors (x, y) = [ (x + dx, y + dy) | dx <- [-1, 0, 1], dy <- [-1, 0, 1], (dx, dy) /= (0, 0) ]

rule :: Grid -> Bool rule grid = neighborAlives == 3 || (neighborAlives == 2 && alive) where neighbors' = experiment neighbors grid neighborAlives = length $ filter id neighbors alive = extract grid

Page 53: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

makeGrid :: [Pos] -> Grid makeGrid xs = Store (`elem` xs) (0, 0)

showCells :: Grid -> IO () showCells grid = sequence_ [ write pos “#" | pos <- [ (i, j) | i <- [1 .. width], j <- [1 .. height] ] , peek pos grid ]

playGameOfLife :: Grid -> IO () playGameOfLife grid = do clearScreen showCells grid playGameOfLife (extend rule grid) -- rule を適用して再帰

gliderDemo = [(0, 2), (1, 0), (1, 2), (2, 1), (2, 2)] main = playGameOfLife (makeGrid gliderDemo)

Page 54: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)
Page 55: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

アプリカティブ関手 Applicative Functor

Page 56: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

F

(C, ⊗C ,1C) (D, ⊗D ,1D)

1C

Lax Monoidal Functor

F(1C) 1Dη

A ⊗C B F(A ⊗C B) F(A) ⊗D F(B)μA,B

Page 57: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

アプリカティブ = Lax Monoidal Functor with strength

class Functor f => Applicative f where unit :: f () -- ≅ () -> f () zip :: f a -> f b -> f (a, b)

F : C → Dη : 1D → F(1C)μA,B : F(A) ⊗D F(B) → F(A ⊗C B)stx,y : A ⊗ F(B) → F(A ⊗ B)

Page 58: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

アプリカティブ関手

class Functor f => Applicative f where unit :: f () unit = pure ()

zip :: f a -> f b -> f (a, b) zip = liftA2 (,)

-- f () ≅ forall a. (() -> a) -> f a (by Yoneda) pure :: a -> f a pure a = fmap (const a) unit

liftA2 :: (a -> b -> c) -> f a -> f b -> f c liftA2 f fa fb = fmap (uncurry f) (zip fa fb)

Page 59: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Day Convolution

data Day f g a = forall b c. Day (f b) (g c) (b -> c -> a)

-- f == g のとき、Day は liftA2 (≒ Applicative) とほぼ同じ dap :: Applicative f => Day f f a -> f a dap (Day fb fc abc) = liftA2 abc fb fc

day :: f (a -> b) -> g a -> Day f g b day fa gb = Day fa gb id -- f == g のとき、 (<*>) :: f (a -> b) -> f a -> f b

(F ⊗Day G)(A) = ∫B

∫C

F(B) × G(C) × Hom(B × C, A)

Page 60: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Profunctor / Arrow

Page 61: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

P

Cop × D Set

⟨C, D⟩ Profunctor

⟨C′ , D′ ⟩

P⟨C, D⟩

P⟨C′ , D′ ⟩

P⟨ f, g⟩ =f gdimap f g

Page 62: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Profunctor

-- C = D = Hask class Profunctor p where dimap :: (c' -> c) -> (d -> d') -> p c d -> p c' d'

-- unzip :: p c (d, d') -> (p c d, p c d') -- unzip p = ((dimap id fst) p, (dimap id snd) p)

-- unzipEither :: p (Either c c') d -> (p c d, p c' d) -- unzipEither p = ((dimap Left id) p, (dimap Right id) p)

P : Cop × D → Set C ↛ Dor

Page 63: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Strong / Choice Profunctor

class Profunctor p => StrongProfunctor p where -- (×) strength first' :: p a b -> p (a, z) (b, z)

class Profunctor p => ChoiceProfunctor p where -- (+) strength left' :: p a b -> p (Either a z) (Either b z)

stA,B,Z = P(A, B) → P(A ⊗ Z, B ⊗ Z)

Page 64: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Arrow

•インスタンス例: (->), Kleisli m, Cokleisli w, Mealy •利用例:並列処理、Arrow-based functional reactive programming

-- Note: Arrow は StrongProfunctor にモノイド対象を加えたものとみなせる class Category a => Arrow a where arr :: (b -> c) -> a b c -- η: Hom :-> a -- (.) :: a z c -> a b z -> a b c -- μ: a^2 :-> a first :: a b c -> a (b, z) (c, z) -- strength -- (&&&) :: a z b -> a z b' -> a z (b, b')

-- Arrow + ChoiceProfunctor class Arrow a => ArrowChoice a where left :: a b c -> a (Either b z) (Either c z) -- (|||) :: a b z -> a b’ z -> a (Either b b’) z

Page 65: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

https://en.wikibooks.org/wiki/Haskell/Understanding_arrows

Page 66: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Profunctor / Arrowの例: 直積・直和の普遍性

Hom( − , A) × Hom( − , B) ≅ Hom( − , A × B)

Hom(A, − ) × Hom(B, − ) ≅ Hom(A + B, − )

Arrow (&&&) と Profunctor (unzip) から

(x -> a, x -> b) ≅ x -> (a, b)

ArrowChoice (|||) と Profunctor (unzipEither) から

(a -> x, b -> x) ≅ Either a b -> x

Page 67: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

A B

C

A × B

HomC(C, A) × HomC(C, B)≅ HomC(C, A × B)

A B

C

A + B

HomC(A, C) × HomC(B, C)≅ HomC(A + B, C)

Page 68: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Optics (Lens)

Page 69: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

init

( )

value : Int

InitializerDecl

FunctionParameterList

ParameterClause

Let’s focus onthis node…

… and edit this node!

Page 70: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

init

( )

value : Int

InitializerDecl

FunctionParameterList

ParameterClause Update!

getter

getter

Page 71: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

init

( )

value : Int

InitializerDecl

FunctionParameterList

ParameterClause

Update!

Update!

getter

getter

setter

setter

Page 72: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

init

( )

value : Int

InitializerDecl

FunctionParameterList

ParameterClause🔍 Lens.parameter

getter

getter

setter

setter

🔍 Lens.rightParen

Page 73: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

init

( )

value : Int

InitializerDecl

FunctionParameterList

ParameterClause

🔍 Lens.parameter >>> Lens.rightParen

deep getter

deep setter

Page 74: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

http://oleg.fi/gists/posts/2017-04-18-glassery.html

Page 75: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Existential Optics

Optic((A, B), (S, T)) = ∫M

C(S, M ⊗ A) × C(M ⊗ B, T)

Lens((A, B), (S, T)) = ∫M

C(S, M × A) × C(M × B, T)

= ∫M

C(S, A) × C(S, M) × C(M × B, T)

= C(S, A) × C(S × B, T)

Prism((A, B), (S, T)) = ∫M

C(S, M + A) × C(M + B, T)

= ∫M

C(S, M + A) × C(M, T) × C(B, T)

= C(S, T + A) × C(B, T)

Page 76: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

P

Cop × C Set

⟨A, B⟩ Profunctor

⟨S, T⟩

P⟨A, B⟩

P⟨S, T⟩

dimap f gf g

Iso射

(Iso)

Page 77: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

−⟨A, B⟩(Profunctor)

Set

P

−⟨S, T⟩

P⟨A, B⟩

P⟨S, T⟩

SetCop×C

Double Yoneda Embedding による、Iso射に同型な Profunctor Iso射

Page 78: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

P

Lens Set

⟨A, B⟩

⟨S, T⟩

P⟨A, B⟩

P⟨S, T⟩

f g

Lens射

Strong Profunctor

Page 79: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

−⟨A, B⟩(StrongProfunctor)

Set

P

−⟨S, T⟩

P⟨A, B⟩

P⟨S, T⟩

SetLens

Double Yoneda Embedding による、Lens射に同型な Profunctor Lens射

Page 80: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Profunctor Optics

ProfOptic((A, B), (S, T)) = [Prof, Set]( − (A, B), − (S, T))

type Optic p s t a b = p a b -> p s t

type Iso s t a b = forall p . Profunctor p => Optic p s t a b

type Lens s t a b = forall p . Strong p => Optic p s t a b

type Prism s t a b = forall p . Choice p => Optic p s t a b

type AffineTraversal s t a b = forall p . (Strong p, Choice p) => Optic p s t a b

Page 81: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

http://oleg.fi/gists/posts/2017-04-18-glassery.html

Page 82: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Recursion Scheme

Page 83: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

再帰と不動点 (例:リスト)

List(A) ≅ 1 + A × List(A)≅ 1 + A × (1 + A × List(A))≅ 1 + A + A2 × List(A)

ListFA(X) ≅ 1 + A × X

Fix(ListFA) ≅ List(A)

とおくと、 ListFA の最小不動点は

Fix(F) ≅ F(Fix(F)) を使って (Fix = Cofix を仮定)

≅ ⋯

左辺に何回 ListF をかけても List(A) で固定

F(Fix(F)) Fix(F)In

out

Page 84: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

F(Fix(F)) Fix(F)

F(A) A

F(Fix(F))Fix(F)

F(A + Fix(F))AF(Fix(F)) Fix(F)

F(Fix(F) × A) A

F(Fix(F))Fix(F)

F(A)ACatamorphism Anamorphism

Paramorphism Apomorphism

In

out

In

out

out

In

out

In

g

g

cata(g)

para(g)

g

F(cata(g))

F(id × para(g)) F(id + apo(g))apo(g)

ana(g)

g

F(ana(g))cataana

para apo

Page 85: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Recursion Scheme (再帰構造の抽象化)

data Fix f = In { out :: f (Fix f) }

cata :: Functor f => (f a -> a) -> Fix f -> a cata g = g . fmap (cata g) . out

para :: Functor f => (f (Fix f, a) -> a) -> Fix f -> a para g = g . fmap (id &&& para g) . out

ana :: Functor f => (a -> f a) -> a -> Fix f ana g = In . fmap (ana g) . g

apo :: Functor f => (a -> f (Either (Fix f) a)) -> a -> Fix f apo g = In . fmap (id ||| apo g) . g

Page 86: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Recursion Scheme (再帰構造の抽象化)

•Catamorphism: F-始代数からの唯一の射、fold

•Anamorphism: F-終余代数への唯一の射、unfold

• Paramorphism: 再帰中に、現在要素以外に元のデータを同時に受け取る (原始再帰、Cata- の拡張版)

•Apomorphism: 余再帰中にデータ構築の早期リターンを可能にしたもの (Ana- の拡張版)

•その他、様々な XXXmorphism が存在する

Page 87: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

https://github.com/sellout/recursion-scheme-talk/blob/master/cheat%20sheet.pdf

Page 88: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Recursion Schemeの例

• ソートアルゴリズム • バブルソート (ana + cata) • 挿入ソート (cata + apo) • 選択ソート (ana + para) • マージソート (hylo) • クイックソート (hylo) • ヒープソート (meta) • 動的計画法 (Dynamorphism) 参考: 挿入ソートと選択ソートは双対 - Qiita

https://qiita.com/lotz/items/a69587882be6e987de4e

Page 89: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

まとめ

Page 90: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

まとめ (圏論のプログラミングへの応用例)

•関手: map、関手の合成 (計算効果の土台)

• 自然変換:ジェネリクス • 米田の補題:CPS, 型計算 • モナド: 計算効果 • コモナド:近傍の畳み込み計算 • アプリカティブ関手:並列計算

• Arrow: 入力付き計算効果 • Optics: データアクセサ • Recursion Scheme: ソートアルゴリズム、動的計画法

Page 91: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

参考文献

• Category Theory for Programmers

• 圏論 | 壱大整域

• Monads Made Difficult

• Haskellと随伴 - Qiita

• kan-extensions

• ChrisPenner/conway

• Generalising Monads to Arrows

• Arrows: A General Interface to Computation

• Don't Fear the Profunctor Optics!

• What You Needa Know about Yoneda - Profunctor Optics and the Yoneda Lemma

• Profunctor Optics: Modular Data Accessors

• Categories of Optics

• Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire

• Curse explicit recursion!

• Recursion Schemes - haskell-shoen

• A Duality of Sorts

Page 92: Category and Programming · 2020. 1. 25. · 近年のプログラミング言語に共通していること •静的型付け言語 + 型推論 •ジェネリクス(多相性)

Thanks! Yasuhiro Inami

@inamiy