前回休みました…
第2期 第10回 H本読書会 in 秋葉原 - H本読書会(Haskell勉強会) | Doorkeeper
- 自動車は型引数を取るべきか?
- 三次元ベクトル
7.5 インスタンスの自動導出
- Showすると文字列表現
- 人間の平等(人間に分かりやすい表現)
- 読み込んでクラスにできてしまう
- Ordクラスの自動導出 比較が出来る
- 何曜日でもいい 自動導出のキーワードをいっぱいくっつける
data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday deriving (Eq, Ord, Show, Read, Bounded, Enum)
- 型シノニム 別名をつける
- 電話帳をかっこよく 型シノニムを使うと、見た目がそれっぽくなる
Haskell プログラマは、自分のプログラムの中で使っている文字列について「ただの文字列じゃなくて実際はこれを表しているんだよ」という情報を伝えたいとき、 String に型シノニムを与えます
- 型シノニムの多相化(連想リストを表す型を作りたいけどキーや値の型は特定せず汎用にしておきたい)
- そこを左に行って、すぐ右へ(Either)
data Either a b = Left a | Right b deriving (Eq, Ord, Read, Show)
7.7 再帰的なデータ構造
代数データ型の値コンストラクタは複数のフィールドを持つこともできるし、フィールドを持たないこともできます。そして各フィールドの型は具体型である必要があります
Haskellのリストはこういうふうに定義されていて、別段特別なものではない。
Prelude> data List a = Empty | Cons { listhead :: a, listTail :: List a} deriving (Show, Read, Eq, Ord) Prelude> Empty Empty Prelude> 5 `Cons` Empty Cons {listhead = 5, listTail = Empty} Prelude> 4 `Cons` (5 `Cons` Empty) Cons {listhead = 4, listTail = Cons {listhead = 5, listTail = Empty}} Prelude> 3 `Cons` (4 `Cons` (5 `Cons` Empty)) Cons {listhead = 3, listTail = Cons {listhead = 4, listTail = Cons {listhead = 5, listTail = Empty}}}
リストの改善
結合性 fixty
木を植えよう
2分探索木を使おうっていうやつ。代数的データ型にはもってこい。
代数的データ型と再帰の組み合わせです。
P139のアレ
7.8 型クラス 中級講座
- 型クラスや、それらにどの型が属しているのか
- Haskell に自動導出してもらうことで独自の型を標準型クラスのインスタンスにする方法
独自の型クラスを作り、そのインスタンスを手動で作る方法を学ぼう
Eq型クラスの内部
内部実装。
class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool x == y = not (x /= y) x /= y = not (x == y)
Eqの型注釈
Prelude> :t (==) (==) :: Eq a => a -> a -> Bool
信号
最小完全定義
インスタンスになろうとする型をクラスの宣伝文句のとおりに振る舞わせるために、最低限定義する必要のある関数たちがある
data TrafficLight = Red | Yellow | Green
Haskellにおけるclassはインターフェイス instanceはクラス定義(一旦Javaのことは忘れよう)
サブクラス化
別の型クラスのサブクラスである型クラスを作ることもできます。
多相型を型クラスのインスタンスに
Maybe が、TrafficLightのような普通の型と違うところは、Maybeそれ自身は具体型ではないところです
Prelude> :info Num class Num a where (+) :: a -> a -> a (*) :: a -> a -> a (-) :: a -> a -> a negate :: a -> a abs :: a -> a signum :: a -> a fromInteger :: Integer -> a -- Defined in `GHC.Num' instance Num Integer -- Defined in `GHC.Num' instance Num Int -- Defined in `GHC.Num' instance Num Float -- Defined in `GHC.Float' instance Num Double -- Defined in `GHC.Float'
Prelude> :info Maybe data Maybe a = Nothing | Just a -- Defined in `Data.Maybe' instance Eq a => Eq (Maybe a) -- Defined in `Data.Maybe' instance Monad Maybe -- Defined in `Data.Maybe' instance Functor Maybe -- Defined in `Data.Maybe' instance Ord a => Ord (Maybe a) -- Defined in `Data.Maybe' instance Read a => Read (Maybe a) -- Defined in `GHC.Read' instance Show a => Show (Maybe a) -- Defined in `GHC.Show'
Prelude> :t ((==) (Just 1)) ((==) (Just 1)) :: (Eq a, Num a) => Maybe a -> Bool
7.9 Yes と No の型クラス
7.10 Functor 型クラス
Functor は、全体を写せる(map over)ものの型クラスです
class Functor f where fmap :: (a -> b) -> f a -> f b
Functor は 1 つの関数 fmap を持っており、デフォルト実装
Prelude> fmap (* 4) [1,2,3] [4,8,12] Prelude> :t fmap fmap :: Functor f => (a -> b) -> f a -> f b
instance Functor [] where fmap = map
難しい…
Maybe は Functor だよ、たぶん
Functor は具体型ではなく、型コンストラクタを要求している
mapとはちょっと違うよっていう話。 gist.github.com
Tree も Functor の森に
TreeでもFunctorは使えるよ。
Either は Functor であるか否か
Eitherはどうなの?
ファンクターはどっちかだけ写すことはできるけど両方を写すことはできない。
Prelude> :i Either data Either a b = Left a | Right b -- Defined in `Data.Either' instance (Eq a, Eq b) => Eq (Either a b) -- Defined in `Data.Either' instance Monad (Either e) -- Defined in `Data.Either' instance Functor (Either a) -- Defined in `Data.Either' instance (Ord a, Ord b) => Ord (Either a b) -- Defined in `Data.Either' instance (Read a, Read b) => Read (Either a b) -- Defined in `Data.Either' instance (Show a, Show b) => Show (Either a b) -- Defined in `Data.Either'
どっちが成功でどっちが失敗かは決まっていない。
7.11 型を司るもの、種類
型とは、値について何らかの推論をするために付いている小さなラベルです。そして、型にも小さなラベルが付いているんです。その名は種類(kind)
りぬーめも Arch Linux on S101: xmonadとHaskell(その13:具体型と型コンストラクタ)
Prelude> :k Int Int :: *
- *は具体型
Prelude> :k Int Int :: * Prelude> :k Either Either :: * -> * -> * Prelude> :k Maybe Maybe :: * -> *
Eitherのスターはカリー化されている。
Prelude> :k Either String Int Either String Int :: * Prelude> :k Either String Either String :: * -> * Prelude> :k Either Either :: * -> * -> *
:t が値の型を調べるコマンドなのと同様、 :k は型の種類を調べるコマンドです。型は値のラベルであり、種類は型のラベルである、という対応関係
P157まで。