読者です 読者をやめる 読者になる 読者になる

by shigemk2

当面は技術的なことしか書かない

第2期 第10回 H本読書会 in 秋葉原 #readhbon

勉強会 Haskell

前回休みました…

第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)

gist.github.com

  • 型シノニム 別名をつける
  • 電話帳をかっこよく 型シノニムを使うと、見た目がそれっぽくなる

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

gist.github.com

木を植えよう

2分探索木を使おうっていうやつ。代数的データ型にはもってこい。

代数的データ型と再帰の組み合わせです。

P139のアレ f:id:shigemk2:20150401203508p:plain

gist.github.com

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のことは忘れよう)

gist.github.com

サブクラス化

別の型クラスのサブクラスである型クラスを作ることもできます。

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

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 の型クラス

gist.github.com

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は使えるよ。

gist.github.com

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まで。