Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.                                             Upcoming SlideShare
×

5,991 views

Published on

Published in: Science
• Full Name
Comment goes here.

Are you sure you want to Yes No
Your message goes here Are you sure you want to  Yes  No
Your message goes here

Are you sure you want to  Yes  No
Your message goes here

Are you sure you want to  Yes  No
Your message goes here

Are you sure you want to  Yes  No
Your message goes here

Are you sure you want to  Yes  No
Your message goes here

1. 1. 圏とHaskellの型 Kinebuchi Tomohiko 2016-07-02 Kinebuchi Tomohiko 圏とHaskellの型
2. 2. 目次 想定聴者 下準備 スライドの表記について 圏論とは プログラムの型とは Haskellの型全体を圏として見る Hask圏 tuple型 Either型 Functor 自然変換 参考文献 宣伝 数学茶屋 Kinebuchi Tomohiko 圏とHaskellの型
3. 3. 想定聴者 プログラムの型は分かるが圏論を知らない人 圏論は知っているがプログラムの型を知らない人 → プログラムの型が圏論を通してどう見えるかを解説してい きます. Kinebuchi Tomohiko 圏とHaskellの型
4. 4. 話すこと Haskellの型の仕組みと圏論の対応 Haskellの型システム 圏論の概念 型 対象 関数 射 tuple 直積 either 直和 Functor 関手 (ある種の関数) 自然変換 Haskellの型システムが圏論に支えられている実例を見ていきま す. Kinebuchi Tomohiko 圏とHaskellの型
5. 5. 話さないこと 圏論一般の説明 前の発表を参照してください プログラムの圏論的意味論 Haskellの文法 Haskellの良いプログラミング この発表を聞いてもHaskellが書けるようになるわけではないで す. 悪しからず. Kinebuchi Tomohiko 圏とHaskellの型
6. 6. 下準備 - スライドの表記について スライドのタイトルに目印を付け, どちら側の話なのかを表し ます. プログラミング側の話→ [プ] 圏論側の話→ [圏] Kinebuchi Tomohiko 圏とHaskellの型
8. 8. [圏] 圏論とは (あくまでこの発表での圏論の使い方ですが) 「対象」と対象どうしをつなぐ「射」やそれらの「性質」とい う言葉で物事を記述する手法. 対象について語るとき, 他の対象との関係の性質という外部か らの視点だけを使い, 「何からできているか?」という内部から の視点を使わないという特徴がある. Kinebuchi Tomohiko 圏とHaskellの型
9. 9. [プ] プログラムの型とは 「型」とはプログラムに登場する値や式の種類のことで, その 役割は プログラムの間違いの検出 整数が期待されているところに文字列が現れるなどの間違 いを事前に見付ける. 抽象化, インターフェースの定義 値や関数の重要な性質だけに着目する. ソースコードを読みやすくする. 「ソースコード」とはプログラムを人間が読める形で記述 したもの. プログラムの最適化 型の情報を使って, より高速なプログラムを生成する. ref.『Types and Programming Languages』(Benjamin C. Pierce) Kinebuchi Tomohiko 圏とHaskellの型
10. 10. [プ][圏] Haskellの型がなす圏 (Hask圏) 対象: 型 射: 一変数関数 恒等射: id関数 (引数をそのまま返す関数) 射の合成: f . g (Haskellの意味での関数の合成) 関数fの変数の型がA, 返り値の型がBのとき, fをAからBへの 射とします. (https://en.wikibooks.org/wiki/Haskell/Category theory) Kinebuchi Tomohiko 圏とHaskellの型
11. 11. [プ][圏] Haskellの型が圏をなすことの説明 恒等射についての条件: 任意の関数f, gに対して f . id == fとid . g == gが成り立ちます. 射の合成についての条件: 任意の関数f, g, hに対して (h . g) . f == h . (g . f)が成り立ちます. → Haskellの型が圏をなすことが分かりました. Kinebuchi Tomohiko 圏とHaskellの型
12. 12. [プ][圏] 例. Hask圏の対象 Integer: 整数の型 String: 文字列の型 Maybe String: 文字列の値がある状態もしくは値が無い状 態を表す型 [Integer]: 整数のリストの型 Kinebuchi Tomohiko 圏とHaskellの型
13. 13. [プ][圏] 例. Hask圏の射 Haskellの世界のdoubleと数学の世界のdoubleの見た目はなんだ か似ている. Haskellの関数double double :: Integer -> Integer -- 関数の型宣言 double x = 2 * x -- 関数の定義 数学の関数double double : Z → Z double(x) = 2x double関数を射と見たときの始域はIntegerで終域もIntegerで す. double関数の型宣言の情報のみを使っていて, 関数の定義 の情報は使っていないことに注意してください. Kinebuchi Tomohiko 圏とHaskellの型
14. 14. [プ][圏] ここまでの内容で質疑応答 「あのスライドをもう1回見せてほしい」 「あそこの解説を聞き逃した」 「あれってどういう意味?」 Kinebuchi Tomohiko 圏とHaskellの型
15. 15. [プ] Haskellの直積型 (tuple型) 型a, bに対し, それらの直積と呼ばれるtuple型(a, b)が存在し, tupleの基本的な関数としてfst, sndがあります. -- | Extract the first component of a pair. fst :: (a,b) -> a fst (x,_) = x -- | Extract the second component of a pair. snd :: (a,b) -> b snd (_,y) = y (https://hackage.haskell.org/package/base-4.9.0.0/docs/ src/Data.Tuple.html#line-33) → これに対応する圏論の概念は何でしょう? Kinebuchi Tomohiko 圏とHaskellの型
16. 16. [圏] 積の復習 圏Cの対象X, Y の積 X × Y, p, q とは, 圏Cの対象X × Y , 射p : X × Y → X, 射q : X × Y → Y の組で, 次の条件を満たす ものです. W k }} ∃1 h l !! X X × Yp oo q // Y (条件) 任意の圏Cの対象Wと射k : W → X, l : W → Y に対し て, 射h : W → X × Y が1つだけあって p ◦ h = k q ◦ h = l となる. Kinebuchi Tomohiko 圏とHaskellの型
17. 17. [プ][圏] 直積型がHask圏の積であること 直積型がHask圏の積になるためには次の条件を満たす必要があ ります. (条件) a, b, cを任意の型とし, k :: c - a, l :: c - bを任意 の関数としたとき, 関数h :: c - (a, b)があって fst . h == k snd . h == l とできる. c k }} ∃1 h l !! a (a, b) fst oo snd // b → h x = (k x, l x)と実装すれば条件を満たします. Kinebuchi Tomohiko 圏とHaskellの型
18. 18. [プ] hの例 作為的な例ですが. k :: (Integer, String, String) - Integer k (x, _, _) = x l :: (Integer, String, String) - String l (_, y, _) = y h :: (Integer, String, String) - (Integer, String) h x = (k x, l x) Kinebuchi Tomohiko 圏とHaskellの型
19. 19. [プ] Haskellの直和型 (Either型) 型a, bに対し, それらの直和と呼ばれるEither型Either a bが存 在し, EitherのコンストラクタとしてLeft, Rightがあります. data Either a b = Left a | Right b deriving (Eq, Ord, Read, Show) (https://hackage.haskell.org/package/base-4.9.0.0/docs/ src/Data.Either.html#Either) → これに対応する圏論の概念は何でしょう? Kinebuchi Tomohiko 圏とHaskellの型
20. 20. [圏] 余積の復習 圏Cの対象X, Y の余積 X Y, i, j とは, 圏Cの対象X Y , 射i : X → X Y , 射j : Y → Y Y の組で, 次の条件を満たす ものです. W X k == i // X Y ∃1 h OO Y j oo l aa (条件) 任意の圏Cの対象Wと射k : X → W, l : Y → Wに対し て, 射h : X Y → Wが1つだけあって h ◦ i = k h ◦ j = l となる. Kinebuchi Tomohiko 圏とHaskellの型
21. 21. [プ][圏] 直和型がHask圏の余積であること 直和型がHask圏の余積になるためには次の条件を満たす必要が あります. (条件) a, b, cを任意の型とし, k :: a - c, l :: b - cを任意 の関数としたとき, 関数h :: Either a b - cがあって h . Left == k h . Right == l とできる. c a k ;; Left // Either a b ∃1 h OO b Right oo l cc Kinebuchi Tomohiko 圏とHaskellの型
22. 22. [プ] hの例 k :: Integer - Integer k x = 2 * x l :: Integer - Integer l x = 3 * x h :: Either Integer Integer - Integer h (Left x) = 2 * x h (Right x) = 3 * x Haskellのパターンマッチでhを定義しているので, 条件を満たす ことが分かりやすくなっています. Kinebuchi Tomohiko 圏とHaskellの型
23. 23. [プ][圏] ここまでの内容で質疑応答 「あのスライドをもう1回見せてほしい」 「あそこの解説を聞き逃した」 「あれってどういう意味?」 Kinebuchi Tomohiko 圏とHaskellの型
24. 24. [プ] HaskellのFunctor 定義は以下の通りです. class Functor f where fmap :: (a - b) - f a - f b (https://hackage.haskell.org/package/base-4.9.0.0/docs/ src/GHC.Base.html#Functor) ある具体的なFunctorをfとして, fの射関数fmapの型を宣言して います. （「射関数」= 関手Fが写す対象と射のうち射の方だけを考え たもの. 射fを射Ffに写す関数のこと.） Kinebuchi Tomohiko 圏とHaskellの型
25. 25. [圏] 関手の復習 圏Cから圏Dへの関手F : C → Dとは, 対応の 組F : Ob(C) → Ob(D), F : HomC(X, Y ) → HomD(FX, FY )であっ て, F1X = 1FX F(g ◦ f) = Fg ◦ Ff を満たすもの. Kinebuchi Tomohiko 圏とHaskellの型
26. 26. [プ] HaskellのFunctor則 (Functor law) Functor則とはFunctorが満たすべき条件. これに反する実装自 体はできるものの, そうするメリットはあまり無いです. fmap id == id fmap (f . g) == fmap f . fmap g (https://hackage.haskell.org/package/base-4.9.0.0/docs/ Data-Functor.html#t:Functor) このFunctor則の2つの条件が, 関手が満たすべき2つの条件に対 応しています. → HaskellのFunctorと圏論での関手に対応 Kinebuchi Tomohiko 圏とHaskellの型
27. 27. [プ] Functorの例: Maybe Maybeとは, ある型の値がある状態と値がない空の状態をいっ ぺんに表せる型です. 定義は以下の通りです. data Maybe a = Nothing | Just a deriving (Eq, Ord) (https://hackage.haskell.org/package/base-4.9.0.0/docs/ src/GHC.Base.html#Maybe) Nothingが「値が無いこと」に対応し, Just aが「aという型の値があること」に対応しています. Kinebuchi Tomohiko 圏とHaskellの型
28. 28. [プ] MaybeがFunctor則を満たすこと (1/2) MaybeのFunctorとしての定義は以下の通りです. instance Functor Maybe where fmap _ Nothing = Nothing fmap f (Just a) = Just (f a) (https://hackage.haskell.org/package/base-4.9.0.0/docs/ src/GHC.Base.html#line-652) Maybe aについてNothingの場合とJust aの場合のそれぞれで Functor則を満たすことを確認すれば良いです. Kinebuchi Tomohiko 圏とHaskellの型
29. 29. [プ] MaybeがFunctor則を満たすこと (2/2) fmap id Nothing == Nothing fmap id (Just a) == Just (id a) == Just a fmap (g . f) Nothing == Nothing ((fmap g) . (fmap f)) Nothing == fmap g (fmap f Nothing) == fmap g Nothing == Nothing fmap (g . f) (Just a) == Just ((g . f) a) == Just (g (f a)) ((fmap g) . (fmap f)) (Just a) == fmap g (fmap f (Just a)) == fmap g (Just (f a)) == Just (g (f a)) Kinebuchi Tomohiko 圏とHaskellの型
30. 30. [プ][圏] Maybeで関数を写してみよう 例: 整数の値を取って, その文字列表現を返す関数int2str. int2str :: Integer - String int2str i = show i この関数をMaybeで写すと, fmap int2str :: Maybe Integer - Maybe String という関数になります. Hask圏 Hask圏 Integer int2str// String Maybe +3 Maybe Integer fmap int2str // Maybe String Kinebuchi Tomohiko 圏とHaskellの型
31. 31. [プ] ghciで動かしてみる \$ ghci Prelude :load int2str.hs Prelude :t int2str int2str :: Integer - String Prelude :t fmap int2str fmap int2str :: Functor f = f Integer - f String Prelude int2str 1 1 Prelude fmap int2str (Just 3) Just 3 Prelude fmap int2str Nothing Nothing Kinebuchi Tomohiko 圏とHaskellの型
32. 32. [プ] Functorの例: List Listとは, ある型の値を0個以上並べたものの型です. 定義は以 下の通りです data [] a = [] | a : [a] (https://hackage.haskell.org/package/ghc-prim-0.4.0.0/ candidate/docs/src/GHC-Types.html#line-33) 右辺の[]が空のリストを表し, a : [a]がリストの前に要素を1つ追加したものを表します. リストの定義では再帰的な定義が使われています. Kinebuchi Tomohiko 圏とHaskellの型
33. 33. [プ] ListがFunctor則を満たすこと (1/3) ListのFunctorとしての定義は以下の通りです. -- The list type instance Functor [] where fmap = map (https://hackage.haskell.org/package/base-4.9.0.0/docs/ src/GHC.Base.html#line-732) Kinebuchi Tomohiko 圏とHaskellの型
34. 34. [プ] ListがFunctor則を満たすこと (2/3) FunctorとしてのListの定義に出てきた map関数の定義は以下の 通りです. map :: (a - b) - [a] - [b] map _ [] = [] map f (x:xs) = f x : map f xs (https://hackage.haskell.org/package/base-4.9.0.0/docs/ src/GHC.Base.html#line-868) Listについて[]の場合とa : [a]の場合のそれぞれで Functor則 を満たすことを確認すれば良いです. Kinebuchi Tomohiko 圏とHaskellの型
35. 35. [プ] ListがFunctor則を満たすこと (3/3) fmap id [] == [] fmap id (x:xs) == id x : map id xs == x : map id xs fmap (g . f) [] == [] ((fmap g) . (fmap f)) [] == fmap g (fmap f []) == fmap g [] == [] fmap (g . f) (x:xs) == (g . f) x : map (g . f) xs == g (f x) : map (g . f) xs ((fmap g) . (fmap f)) (x:xs) == fmap g (fmap f (x:xs)) == fmap g (f x : map f xs) == g (f x) : (map g) ((map f) xs) == g (f x) : ((map g) . (map f) xs) == g (f x) : map (g . f) xs Kinebuchi Tomohiko 圏とHaskellの型
36. 36. [プ][圏] Listで関数を写してみよう 例: 整数の値を取って, その文字列表現を返す関数int2str. int2str :: Integer - String int2str i = show i この関数をListで写すと, fmap int2str :: [Integer] - [String] という関数になります. Hask圏 Hask圏 Integer int2str// String List +3 [Integer] fmap int2str // [String] Kinebuchi Tomohiko 圏とHaskellの型
37. 37. [プ] ghciで動かしてみる \$ ghci Prelude :load int2str.hs Prelude :t int2str int2str :: Integer - String Prelude :t fmap int2str fmap int2str :: Functor f = f Integer - f String Prelude int2str 1 1 Prelude fmap int2str [1, 2, 3] [1,2,3] Prelude fmap int2str [] [] Kinebuchi Tomohiko 圏とHaskellの型
38. 38. [プ][圏] ここまでの内容で質疑応答 「あのスライドをもう1回見せてほしい」 「あそこの解説を聞き逃した」 「あれってどういう意味?」 Kinebuchi Tomohiko 圏とHaskellの型
39. 39. [圏] 自然変換の復習 圏C, Dと関手F, G : C → Dがあったとき, 自然変換α : F → Gと は射の集まりαX : FX → GX (X ∈ Ob(C))であって, ∀f : X → Y に対しαY ◦ Ff = Gf ◦ αXを満たすもの X f // Y FX Ff // αX FY αY GX Gf // GY → さてHask圏で自然変換になるものは何があるでしょう? Kinebuchi Tomohiko 圏とHaskellの型
40. 40. [プ] 例. リストの先頭の要素を取り出す関数 リストの1つ目の要素を取り出す関数takeFirstを次のように定 義します. リストが空だった場合はNothingを返しておきます. takeFirst :: [a] - Maybe a takeFirst [] = Nothing takeFirst (x:xs) = Just x プログラミングに出てくる自然変換では, 型変数aが何かには 依存しない場合が多いです. (むしろ依存されると気持ち悪いで す.) Kinebuchi Tomohiko 圏とHaskellの型
41. 41. [プ] takeFirstは自然変換 takeFirstは自然変換なので, 整数のリストからそれぞれの要素の文字列表現のリストを 作り, その先頭の要素を取り出す処理 (→↓のルート) 整数のリストの先頭の要素を取り出して, 整数をその文字 列表現に変換する処理 (↓→のルート) が同じ結果になります. [Integer] fmap int2str // takeFirst [String] takeFirst Maybe Integer fmap int2str // Maybe String Kinebuchi Tomohiko 圏とHaskellの型
42. 42. [プ] 具体的な値でtakeFirstの動きを見ましょう [1, 2, 3] fmap int2str // _ takeFirst [1,2,3]_ takeFirst Just 1 fmap int2str // Just 1 [] fmap int2str // _ takeFirst []_ takeFirst Nothing fmap int2str // Nothing Kinebuchi Tomohiko 圏とHaskellの型
43. 43. 参考文献 『すごいHaskellたのしく学ぼう!』(Miran Lipovaca・著／ 田中英行・村主崇行・共訳) WikiBooks「Haskell/Category theory」 https: //en.wikibooks.org/wiki/Haskell/Category theory Hackage https://hackage.haskell.org/ 『圏論の基礎』(S.マックレーン著, 三好博之／高木理訳) 『Types and Programming Languages』(Benjamin C. Pierce) 『型システム入門』(住井英二郎監訳, 遠藤侑介・酒井政裕 ・今井敬吾・黒木裕介・今井宜洋・才川隆文・今井健男共 訳) Kinebuchi Tomohiko 圏とHaskellの型
44. 44. 数学茶屋 「フリートーク中心の数学好きの集まり」 和コンセプト 時期は9月 場所は渋谷近辺 人数は20人くらい Facebook → https://www.facebook.com/MathTeaHouse Kinebuchi Tomohiko 圏とHaskellの型
45. 45. [プ][圏] おしまい Haskellの型と圏論の概念の対応 (再掲) Haskellの型システム 圏論の概念 型 対象 関数 射 tuple型 直積 Either型 直和 Functor 関手 Listのtakeなど 自然変換 Kinebuchi Tomohiko 圏とHaskellの型