240 likes | 376 Views
全体ミーティング 2010/05/19. 渡邊 裕貴. 今日の内容. 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. Haskell の ADT ( 普通のバリアント ). リストの例
E N D
全体ミーティング2010/05/19 渡邊 裕貴
今日の内容 • 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.
Haskell の ADT (普通のバリアント) • リストの例 • List 型のコンストラクタとして Nil と Cons を定義 dataList a = Nil |Cons a (List a) • ちなみに OCaml では type'a list =Nil |Cons of'a * 'a list
Haskell の ADT (普通のバリアント) • コンストラクタをリストを返す関数と見なすと data List a where Nil ::List a Cons :: a -> List a -> List a ここは型変数 aでなければいけない ここを拡張したい
Generalized algebraic data types (GADT) • コンストラクタの戻り値の型パラメータを指定できる • GHC よる拡張 • 式を表すデータ型の例 dataTerm a where IntLiteral::Int -> Term Int Add :: Term Int -> Term Int -> Term Int Eq:: Term Int-> Term Int-> Term Bool IfThenElse:: Term Bool -> Term a -> Term a -> Term a
GADT (続き) • 式を評価する関数の例 eval:: Term a -> a eval (IntLiteral v) = v eval (Add a b) =eval a + eval b eval (Eq a b) =eval a == eval b eval (IfThenElse c t f) = if eval c then evalt else eval f • パターンマッチング時に型が正しく refine されるので、この関数は well-typed である
GADT (続き) • 実用例 • バージョン管理システム darcs でパッチの等価性を型で定式化して扱うのに使われているらしい…… dataPair 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 より引用、一部改変
Type families • 型から型への関数のようなもの • GHC による拡張 • 型で自然数の加算を表現する例 data Zero data Succ a type family Add a b type instance Add Zero a = a type instance Add (Succ a) b = Succ (Add a b) • あくまでも型なので、コンパイル時に計算される コンストラクタのない型
Bounded vectors • 要素数を型で表すリスト dataVec e lenwhere Nil ::Vec e Zero Cons :: e -> Vec e len -> Vec e (Succlen) vappend::Vec e n -> Vec e m -> Vec e (Add n m) vappend Nil ys=ys vappend (Cons x xs) ys= Cons x (vappendxsys) vec1 ::Vec Char (Succ (Succ Zero)) vec1 =vappend (Cons '1' Nil) (Cons '2' Nil)
Generic map • キーの型に応じてデータ構造を変えるマップ data familyGMapk v data instanceGMapInt v =GMapInt [(Int, v)] -- GMapInt :: [(Int, v)] -> GMapInt v data instanceGMap () v =GMapUnit (Maybe v) -- GMapUnit :: Maybe v -> GMap () v data instanceGMap (Either a b) v =GMapEither (GMap a v) (GMap b v) -- GMapEither :: GMap a v -> GMap b v -> GMap (Either a b) v
A type-preserving compiler in Haskell • Haskell で書かれた type-preserving compiler • Haskell の型システムを用いて type preserving を証明 • その中で GADT や type families を使っている • 入力言語:System F(型多相なラムダ計算) • 出力言語: ??? • アセンブリを吐くところまではできていないらしい
コンパイルの流れ レジスタ割当、機械語生成、最適化は future work
対象言語の内部表現 • Higher-order abstract syntax (HOAS) • De Bruijn indices • いずれの形式も対象言語で well-typed でない式はHaskell の式としても well-typed でない • コンパイルの過程の最初の方では HOAS を用い、途中から de Bruijnに移行
コードの表し方 (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 による
コードの表し方 (2) • De Bruijn indices • 変数をインデックスで表す • インデックスは、自身から見ていくつ外側の λ を指しているかを表す λz. (λy. y (λx. x)) (λx. zx) ↓ 図は http://en.wikipedia.org/wiki/File:De_Bruijn_index_illustration_1.svg による
コードの表し方 (2) • De Bruijn indices 形式の Haskell での表現 data Exp ts t where Num ::Int -> Exp tsInt Add :: Exp tsInt -> Exp tsInt -> Exp tsInt 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 tsは型環境を表す
コードの表し方 (2) • De Bruijn indices の Haskell での表現の例 let x = 1 + 2 in x + 3 ↓ Let (Add (Num 1) (Num 2)) (Add (VarIzero) (Num 3)) Add (Num 1) (Num 2) :: Exp tsInt Izero :: Index (Int, ts) Int VarIzero :: Exp (Int, ts) Int Add (VarIzero) (Num 3) :: Exp (Int, ts) Int Let (Add …) (Add …) :: Exp tsInt
型の表し方 • 対象言語の型も de Bruijn indices で表される ∀α. ∀β. (α, β) → (β, α) ↓ All (All ((Var (S Z), Var Z) -> (Var Z, Var (S Z)))) • 型変数の置換などは type families を用いて定義される • GHC では本当の型から型への関数は使えないので対象言語の型を HOAS で表すことはできない
型の表し方 • CPS 変換における型の変換 • Type families で以下のように定義される type familyKtype t type instanceKtype (t1 -> t2) = Cont Z (Ktype t1, Cont Z (Ktype t2)) type instanceKtype (All t) = Cont (S Z) (Cont Z (Ktype t)) type instanceKtype (Vari) =Vari … ⋮
Type preservation • CPS 変換の type preservation • 変換前のコードが well-typed ならば変換後のコードも well-typed である • 変換を行う Haskell 関数の型がそれを保証 cps :: Exp t -> (ValK (Ktype t) -> ExpK) -> ExpK
表現形式の選択 • CPS 変換 • HOAS を用いる • De Bruijnよりもエレガントに書ける • クロージャ変換 / hoisting • De Bruijnindices を用いる • HOAS では項が閉じていることを表せない • でも複雑で混乱する
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_datatype • “First-Class Phantom Types” • J. Cheney and R. Hinze • Technical Report CUCIS TR2003-1901, Cornell University, 2003.
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.
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.