28
. . . . . . 7.7 再帰的なデータ構造 . . . . . . . . 7.8 型クラス 中級講座 . . 7.9 Yes No の型クラス . . . . . . . 7.10 Functor 型クラス . . 7.11 型を司るもの、種類 . . すごい Haskell 読書会 in 大阪 #6 — 6. 型や型クラスを自分で作ろう (2) — @cojna 2013 3 8

すごいHaskell読書会 in 大阪 #6

  • Upload
    cojna

  • View
    556

  • Download
    1

Embed Size (px)

Citation preview

Page 1: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

.

......

すごいHaskell読書会 in 大阪 #6— 6. 型や型クラスを自分で作ろう (2) —

@cojna

2013年 3月 8日

Page 2: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

本日の内容

7.7 再帰的なデータ構造

7.8 型クラス 中級講座

7.9 Yes と No の型クラス

7.10 Functor 型クラス

7.11 型を司るもの、種類

Page 3: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

前回の復習

.データ型の作り方........data Maybe a = Nothing | Just a deriving (Eq, Ord)

Maybe : 型コンストラクタ (具体型ではない)f :: Maybe → Int のような関数は作れない

a : 型引数 (具体型)

Maybe a : 具体型

Just : 値コンストラクタ

Page 4: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

リスト

[3, 4, 5, 6] というのは構文糖衣.

[3, 4, 5, 6]=⇒ 3 : (4 : (5 : (6 : [])))=⇒ 3 : 4 : 5 : 6 : []

ということで,リストを作っていきましょう!

Page 5: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

リスト

.リスト型..

...... data List a = Empty | Cons a (List a)

レコード構文で書くと

data List a = Empty | Cons { listHead :: a

, listTail :: List a

}

Empty は []

Cons x xs は x : xs に対応する

Page 6: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

リストの改善

.リスト型’..

......

infixr 5 : -:

data List a = Empty | a : -: (List a)

記号文字だけで値コンストラクタに出来る名前はコロン :から始めないといけない:: は使えないコロン :から始まる二項演算子は定義できない× x : + y = x + y,⃝ x + : y = x + yコロンは大文字として考える (@nushioさん)

infix, infixl, infixr で結合性を定めることが出来るデフォルトは infixl 9例) infixl 7 ∗, infixl 6 +,infixl 6 ‘xor‘,infixr 5 ‘Cons‘

Page 7: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

リストの改善

.(++)..

......

infixr 5 ˆ++

(ˆ++) :: List a → List a → List a

Empty ˆ++ ys = ys

(x : -: xs) ˆ++ ys = x : -: (xs ˆ++ ys)

パターンマッチも使える!!

Page 8: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

二分探索木

.二分探索木..

......

二分木

左の子 < 親 < 右の子

5

����3 7

����6 8

Page 9: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

二分探索木

.二分探索木データ型........data Tree a = EmptyTree | Node a (Tree a) (Tree a)

簡単のため平衡木にはしません挿入,探索をする

treeInsert :: a → Tree a → Tree atreeElem :: a → Tree a → Bool

を実装していきます

Page 10: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

7.8 型クラス 中級講座

Java や Python のような言語に出てくる「クラス」とは何の関係もありません.

Page 11: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

クラス

.Eq型クラス..

......

class Eq a where

(==), (/ =) :: a → a → Bool

x == y = not (x / = y)

x / = y = not (x == y)

補足Eqは等値性を表すクラスですが,EQはOrdering型の値です.data Ordering = LT | EQ | GT

Page 12: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

インスタンス宣言

.交通信号データ型を Eqのインスタンスに..

......

data TrafficLight = Red | Yellow | Greeninstance Eq TrafficLight where

Red == Red = True

Yellow == Yellow = True

Green == Green = True

== = False

(/ =)まで定義しなくて良い =⇒ 最小完全定義

Page 13: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

インスタンス宣言

.Showのインスタンスに..

......

instance Show TrafficLight where

show Red = “Red light”

show Yellow = “Yellow light”

show Green = “Green light”

Page 14: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

サブクラス化

.Num クラス........class (Eq a) ⇒ Num a where (以下省略)

Num は Eq のサブクラス

Eq は Num のスーパークラス

Num のインスタンスに出来るのは Eq クラスのものだけ

a を Num のインスタンスにしようと思うと Eq のインスタンスにしないといけない

(ちなみに GHC 7.4.1 で Eq を Num のスーパークラスにするという制約は取り除かれました.)

Page 15: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

多相型を型クラスのインスタンスに

.問題..

......

Maybe を Eq のインスタンスにするにはどうすればいいか?

class Eq a where

(==), (/ =) :: a → a → Bool

x == y = not (x / = y)

x / = y = not (x == y)

Maybe は具体型ではないので,instance Eq Maybe where と出来ない.

Page 16: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

多相型を型クラスのインスタンスに

.Maybeを Eqのインスタンスに..

......

instance Eq (Maybe a) where

Just x == Just y = x == y

Nothing == Nothing = True

/ = = False

Maybeは具体型ではないが,Maybe aは具体型.しかし,まだ1つ問題が残っています.a が Eq のインスタンスになっていないと x == y が使えない.

Page 17: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

多相型を型クラスのインスタンスに

.Maybeを Eqのインスタンスに (完成版)..

......

instance (Eq a) ⇒ Eq (Maybe a) where

Just x == Just y = x == y

Nothing == Nothing = True

/ = = False

Page 18: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

7.9 Yes と No の型クラス

if (0) alert(“YEAH!”) else alert(“No!”)

if (“”) alert(“YEAH!”) else alert(“No!”)

if (false) alert(“YEAH!”) else alert(“No!”)

JavaScriptではこのコードはすべて No! というアラートを表示しますが,真理値をBool型しか認めないHaskellではこういうことはできません.ここでは,Bool型でないものも真理値として使えるようなYesNo型 クラスを実装します.

Page 19: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

YesNo型クラス

.YesNo型クラス..

......

class YesNo a where

yesno :: a → Bool

Int, [a], Bool, Maybe a, Tree a, TrafficLightを YesNo のインスタンスにします.

YesNo 用の ifっぽい関数 yesnoIf

Page 20: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

Functor(関手)型クラス

.Functor 型クラス..

......

class Functor f where

fmap :: (a → b) → f a → f b

map :: (a → b) → [a] → [b]に似てるなぁ

f a が具体型なので,f は型引数を 1つもつ型コンストラクタ(クラスに出来るのは具体型だけではない)fmapは Functor則を満たさないといけない

fmap id = idfmap f . fmap g = fmap (f . g)

詳細は 11章

Page 21: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

リスト Functor

.リストを Functorに..

......

instance Functor [] where

fmap = map

instance Functor [a] where ではない

[] は空リストではなくて [] aの []

fmap :: (a → b) → [] a → [] b

Page 22: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

Maybe Functor

.Maybeを Functorに..

......

instance Functor Maybe where

fmap Nothing = Nothing

fmap f (Just a) = Just (f a)

instance Functor (Maybe a) where ではないfmap :: (a → b) → Maybe a → Maybe b

左のNothingはMaybe a型右のNothingはMaybe b型

fmap f (Just a) = Just (f a)

fmap x = x

は型エラー

Page 23: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

Tree Functor

.Treeを Functorに..

......

data Tree a = EmptyTree | Node a (Tree a) (Tree a)

instance Functor Tree where

fmap EmptyTree = EmptyTree

fmap f (Node x left right)

= Node (f x) (fmap f left) (fmap f right)

Page 24: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

Tree Functor

注意点

f が順序を保存するような関数でないと fmap したあとの木が二分探索木になっているとは限らない.例えば,Tree Intに対して fmap negateすると大小関係が入れ替わって「左の子<親<右の子」が成り立たなくなる.

二分木にはなっている.

Page 25: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

Either Functor

.Eitherを Functorに..

......

instance Functor (Either a) where

fmap (Left x) = Left x

fmap f (Right y) = Right (f y)

型引数が複数ある時は部分適用させる

fmap :: (b → c) → Either a b → Either a c

よく使う方をRightにした方がよさそうですよね

Page 26: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

読者への練習問題

.問題..

......

Data.Map も Functor にできます.どのように Functor のインスタンスになるでしょうか?

とりあえず,fmapの型は...fmap :: (a → b) → Map k a → Map k b

Hoogle にきいてみると...

Page 27: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

種類

種類 (kind) : 型の型みたいなもの

: t は値の型を調べるコマンド

: k は型の種類を調べるコマンド

具体型は ∗Functorは ∗ → ∗

Page 28: すごいHaskell読書会 in 大阪 #6

. . . . . .7.7 再帰的なデータ構造

. . . . . . . .7.8 型クラス 中級講座

. .7.9 Yes と No の型クラス

. . . . . . .7.10 Functor 型クラス

. .7.11 型を司るもの、種類

演習

Functorクラスのインスタンスにして下さい.

data Akari a = Waai a (Akari a) | Daisuki

data H oo gle = H oo oo oo oo oo gle

data Ha y oo = Ha y oo oo oo oo oo

data O b = OOOO|OOOOOO|O|OO

data Hom r a = Hom (r → a)

data State s a = State (s → (a, s))

data Just a = Nothing | Maybe (Maybe a)

ヒント

作るのはmap関数みたいなもの

とりあえず型を合わせる

fmap id が id になるように (Functor則の1つ)