全体ミーティング 2010/05/19 渡邊 裕貴 1 今日の内容 • Haskell の型システムの拡張について – Generalized algebraic data types (GADT) – Type families • それを利用して実装された type-preserving compiler について – “A type-preserving compiler in Haskell.” L.J. Guillemette and S. Monnier. ICFP 2008. 2 Haskell の ADT (普通のバリアント) • リストの例 – List 型のコンストラクタとして Nil と Cons を定義 data List a = Nil | Cons a (List a) – ちなみに OCaml では type 'a list = Nil | Cons of 'a * 'a list 3 Haskell の ADT (普通のバリアント) • コンストラクタを リストを返す関数と見なすと data List a where Nil :: List a Cons :: a -> List a -> List a ここは型変数 a でなければいけない ここを拡張したい 4 Generalized algebraic data types (GADT) • コンストラクタの戻り値の型パラメータを指定 できる – GHC よる拡張 • 式を表すデータ型の例 data Term a where IntLiteral :: Add :: Eq :: IfThenElse :: Int -> Term Int Term Int -> Term Int -> Term Int Term Int -> Term Int -> Term Bool Term Bool -> Term a -> Term a -> Term a 5 GADT (続き) • 式を評価する関数の例 eval eval eval eval eval :: Term a -> a (IntLiteral v) (Add a b) (Eq a b) (IfThenElse c t f) = = = = v eval a + eval b eval a == eval b if eval c then eval t else eval f – パターンマッチング時に型が正しく refine される ので、この関数は well-typed である 6 GADT (続き) • 実用例 – バージョン管理システム darcs で パッチの等価性を型で定式化して扱うのに 使われているらしい…… data Pair a b where Pair :: a -> b -> Pair a b SymmetricPair :: a -> a -> Pair a a foo :: Pair a b -> b foo (Pair x y) = y foo (SymmetricPair x y) = x http://web.archive.org/web/20070929093300/http://darcs.net/fosdem_talk/talk.pdf p. 14 より引用、一部改変 7 Type families • 型から型への関数のようなもの – GHC による拡張 • 型で自然数の加算を表現する例 data data type type type Zero コンストラクタのない型 Succ a family Add a b instance Add Zero a = a instance Add (Succ a) b = Succ (Add a b) – あくまでも型なので、コンパイル時に計算される 8 Bounded vectors • 要素数を型で表すリスト data Vec e len where Nil :: Vec e Zero Cons :: e -> Vec e len -> Vec e (Succ len) vappend :: Vec e n -> Vec e m -> Vec e (Add n m) vappend Nil ys = ys vappend (Cons x xs) ys = Cons x (vappend xs ys) vec1 :: Vec Char (Succ (Succ Zero)) vec1 = vappend (Cons '1' Nil) (Cons '2' Nil) 9 Generic map • キーの型に応じてデータ構造を変えるマップ data family GMap k v data instance GMap Int v = GMapInt [(Int, v)] -- GMapInt :: [(Int, v)] -> GMap Int v data instance GMap () v = GMapUnit (Maybe v) -- GMapUnit :: Maybe v -> GMap () v data instance GMap (Either a b) v = GMapEither (GMap a v) (GMap b v) -- GMapEither :: GMap a v -> GMap b v -> GMap (Either a b) v 10 A type-preserving compiler in Haskell • Haskell で書かれた type-preserving compiler • Haskell の型システムを用いて type preserving を証明 – その中で GADT や type families を使っている – 入力言語: System F (型多相なラムダ計算) – 出力言語: ??? • アセンブリを吐くところまではできていないらしい 11 コンパイルの流れ •CPS 変換 •De Bruijn index 化 •クロージャ変換 •Hoisting レジスタ割当、機械語生成、最適化は future work 12 対象言語の内部表現 • Higher-order abstract syntax (HOAS) • De Bruijn indices – いずれの形式も 対象言語で well-typed でない式は Haskell の式としても well-typed でない – コンパイルの過程の最初の方では HOAS を用い、 途中から de Bruijn に移行 13 コードの表し方 (1) • Higher-order abstract syntax (HOAS) – 対象言語での変数束縛を Haskell 内での束縛に 直す data Exp t where Add :: Exp Int -> Exp Int -> Exp Int Let :: Exp t1 -> (Exp t1 -> Exp t2) -> Exp t2 … let x = 1 + 2 in x + 3 ↓ Let (Add (Num 1) (Num 2)) (λx. Add x (Num 3)) 例は http://en.wikipedia.org/wiki/Higher-order_abstract_syntax による 14 コードの表し方 (2) • De Bruijn indices – 変数をインデックスで表す • インデックスは、自身から見ていくつ外側の λ を 指しているかを表す λz. (λy. y (λx. x)) (λx. z x) ↓ 図は http://en.wikipedia.org/wiki/File:De_Bruijn_index_illustration_1.svg による 15 コードの表し方 (2) • De Bruijn indices 形式の Haskell での表現 data Exp ts t where ts は型環境を表す Num :: Int -> Exp ts Int Add :: Exp ts Int -> Exp ts Int -> Exp ts Int App :: Exp ts (t1 -> t2) -> Exp ts t1 -> Exp ts t2 Var :: Index ts t -> Exp ts t Let :: Exp ts s -> Exp (s, ts) t -> Exp ts t … data Index ts t where Izero :: Index (t, ts) t Isucc :: Index ts t -> Index (s, ts) t 16 コードの表し方 (2) • De Bruijn indices の Haskell での表現の例 let x = 1 + 2 in x + 3 ↓ Let (Add (Num 1) (Num 2)) (Add (Var Izero) (Num 3)) Add (Num 1) (Num 2) :: Izero :: Var Izero :: Add (Var Izero) (Num 3) :: Let (Add …) (Add …) :: Exp ts Int Index (Int, ts) Int Exp (Int, ts) Int Exp (Int, ts) Int Exp ts Int 17 型の表し方 • 対象言語の型も de Bruijn indices で表される ∀α. ∀β. (α, β) → (β, α) ↓ All (All ((Var (S Z), Var Z) -> (Var Z, Var (S Z)))) – 型変数の置換などは type families を用いて定義 される – GHC では本当の型から型への関数は使えないので 対象言語の型を HOAS で表すことはできない 18 型の表し方 • CPS 変換における型の変換 ⋮ • Type families で以下のように定義される type family Ktype t type instance Ktype (t1 -> t2) = Cont Z (Ktype t1, Cont Z (Ktype t2)) type instance Ktype (All t) = Cont (S Z) (Cont Z (Ktype t)) type instance Ktype (Var i) = Var i … 19 Type preservation • CPS 変換の type preservation – 変換前のコードが well-typed ならば 変換後のコードも well-typed である – 変換を行う Haskell 関数の型がそれを保証 cps :: Exp t -> (ValK (Ktype t) -> ExpK) -> ExpK 20 表現形式の選択 • CPS 変換 – HOAS を用いる • De Bruijn よりもエレガントに書ける • クロージャ変換 / hoisting – De Bruijn indices を用いる • HOAS では項が閉じていることを表せない • でも複雑で混乱する 21 References • 7.4. Extensions to data types and type synonyms – In The Glorious Glasgow Haskell Compilation System User's Guide, Version 6.12.2. – http://www.haskell.org/ghc/docs/6.12.2/html/users_guide/data -type-extensions.html • Generalized algebraic datatype – In HaskellWiki – http://www.haskell.org/haskellwiki/Generalised_algebraic_data type • “First-Class Phantom Types” – J. Cheney and R. Hinze – Technical Report CUCIS TR2003-1901, Cornell University, 2003. 22 References • 7.7. Type families – In The Glorious Glasgow Haskell Compilation System User's Guide, Version 6.12.2. – http://www.haskell.org/ghc/docs/6.12.2/html/users_guide /type-families.html • Type families – In HaskellWiki – http://www.haskell.org/haskellwiki/GHC/Type_families • “Associated Types with Class” – M. Chakravarty, G. Keller, S. Peyton-Jones, and S. Marlow – In Proc. of The 32nd Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, p.p. 1—13, ACM Press, 2005. 23 References • “Type Associated Type Synonyms”. – M. Chakravarty, G. Keller, S. Peyton-Jones, and S. Marlow – In Proc. of The 10th ACM SIGPLAN International Conference on Functional Programming, p.p. 241—253, ACM Press, 2005. • “Type Checking with Open Type Functions” – T. Schrijvers, S. Jones, M. Chakravarty, and M. Sulzmann – In Proc. of The 13th ACM SIGPLAN International Conference on Functional Programming, p.p. 51—62, ACM Press, 2008. • “A Type-Preserving Compiler in Haskell.” – L.J. Guillemette and S. Monnier. – In Proc. of the 13th ACM SIGPLAN International Conference on Functional Programming, p.p. 75—86, ACM Press, 2008. 24
© Copyright 2024 ExpyDoc