Haskellの型クラス

@coord_e

『Haskellの型クラス』 @coord_e

Haskellとはなんですか?

こういう感じの関数型言語です(省略)

  • 関数適用: f x
  • 関数定義: f x = e
  • 型アノテーション: x :: t

型とはなんですか?

ここでは式を分類します(省略)

『Haskellの型クラス』 @coord_e

型クラスっていうのがあるらしいです

『Haskellの型クラス』 @coord_e

話すこと

  • 型クラスの型推論の実装イメージ
  • 型クラスによるオーバーロードの実装イメージ
『Haskellの型クラス』 @coord_e

型クラスがやること

  1. 型を分類することで抽象化
  2. 名前がぶら下がっているので名前と実装の分離ができる
  • オーバーロードとも
  • 型クラスと名前、型と実装が紐ついている
『Haskellの型クラス』 @coord_e

実装

  • 制約があったときに、
    マッチするインスタンス宣言があったら制約を解消
  • 例:
    member 'a' ['b', 'c'] :: Eq Char => Bool
    
    • instance Eq Char のインスタンス宣言が存在するので、Eq Charを解消
    • Bool に型付け
『Haskellの型クラス』 @coord_e

だけじゃない

instance (Eq a, Eq b) => Eq (a, b) where
  eq (x1, y1) (x2, y2) = eq x1 x2 && eq y1 y2
  • (Eq a, Eq b)なときに限り、Eq (a, b)
  • 定義中で a b に対する
    eq が使われていることに注意
『Haskellの型クラス』 @coord_e

クラス制約

class Eq a => Ord a where
  lt :: a -> a -> Bool
  gt :: a -> a -> Bool
  ...
  • Ord aEq a, Ord a と同じ意味になる
  • Ord t のインスタンス宣言時に Eq t でないとエラー
  • Eq a, Ord a と制約があったときに Ord a にまとめて見た目を綺麗にできる
『Haskellの型クラス』 @coord_e

はい

  • こんな方法でHMに手を加えれば型推論はできる
    • Jones, Mark P. "Typing haskell in haskell." Haskell workshop. Vol. 7. 1999.
  • 実際はHNF(Head-Normal Form)に到達するまで
    繰り返すので、停止するんですか?という話があるが…
    • 停止するんですか議論はよくわかっとらんスマン
    • ナントカconditionというのがあります
『Haskellの型クラス』 @coord_e

実装の選択の実装

『Haskellの型クラス』 @coord_e

型クラスがやること

  1. 型を分類することで抽象化
  2. 名前がぶら下がっているので名前と実装の分離ができる(オーバーロード)
『Haskellの型クラス』 @coord_e

実装

  • C t の制約があったときに、
    マッチするインスタンス宣言があったらC t
    マッチするインスタンス宣言の制約と置き換え
    制約を発生させた名前に対応する辞書を渡す
『Haskellの型クラス』 @coord_e

これから例をお見せします

  • x@d で名前 x に辞書 d を渡すことにします
  • x@d = ... で辞書 dを受け取る名前 x
    定義することにします
  • ただの関数適用で実装しても特に問題ない
『Haskellの型クラス』 @coord_e

定義側の例

member x [] = False
member x (h : t) | eq x h    = True
                 | otherwise = member x t
  1. eq から Eq a が登場し下のように型が付く(省略)
member :: Eq a => a -> a -> Bool
『Haskellの型クラス』 @coord_e

定義側の例

member@dict x [] = False
member@dict x (h : t) | eq@dict x h = True
                      | otherwise   = member x t
  1. Eq a にマッチするインスタンスはなく、
    受け取った辞書をそのまま使うようにする
  2. 汎化
member :: forall a. Eq a => a -> a -> Bool
『Haskellの型クラス』 @coord_e

使用側の例

member (True, 'a') [] :: Eq (Bool, Char) => Bool
『Haskellの型クラス』 @coord_e

使用側の例

-- `eqBool` は `Eq Bool` の実装が入った辞書
member@(eqPair@eqBool) (True, 'a') [] :: Eq Char => Bool
  1. instance Eq Bool が存在するので解消
  • Eq Bool の発生源は eqPair なので、
    eqPair に辞書を渡す
『Haskellの型クラス』 @coord_e

使用側の例

-- `eqChar` は `Eq Char` の実装が入った辞書
member@(eqPair@eqBool@eqChar) (True, 'a') [] :: Bool
  1. instance Eq Char が存在するので解消
  • Eq Char の発生源は eqPair なので、
    eqPair に辞書を渡す
『Haskellの型クラス』 @coord_e

はい

  • 型推論の過程で辞書をうまく受け渡すことで実装できる
  • Dictionary Passingについて...
    • Demystifying Type Classes - http://okmij.org/ftp/Computation/typeclass.html
    • Wadler, Philip, and Stephen Blott. "How to make ad-hoc polymorphism less ad hoc." Proceedings of the 16th ACM SIGPLAN-SIGACT symposium on Principles of programming languages. ACM, 1989.
『Haskellの型クラス』 @coord_e

コンストラクタクラスについて

『Haskellの型クラス』 @coord_e

コンストラクタクラス

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

instance Functor [] where
  fmap = map

instance Functor Maybe where
  fmap f (Just x) = Just (f x)
  fmap _ Nothing  = Nothing
『Haskellの型クラス』 @coord_e

まとめ

『Haskellの型クラス』 @coord_e

話したこと

  • 型クラスというのがあって、名前と実装が分離できる
  • HM型推論にチョコっと手を加えることで
    型推論の過程で変換を行い実装できる
  • コンストラクタクラスというのがある
『Haskellの型クラス』 @coord_e

ありがとうございました

👇スライド👇

coord-e.github.io/slide-type-class-lt

『Haskellの型クラス』 @coord_e

textlint-disable terminology

textlint-enable terminology