2010/05/19

全体ミーティング
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