次は、依存型のラムダ計算の構文です。バウンドを使用した相互再帰構文
data TermI a = Var a
| App (TermI a) (TermC a) -- when type-checking an application, infer the type of the function and then check that its argument matches the domain
| Star -- the type of types
| Pi (Type a) (Scope() Type a) -- The range of a pi-type is allowed to refer to the argument's value
| Ann (TermC a) (Type a) -- embed a checkable term by declaring its type
deriving (Functor, Foldable, Traversable)
data TermC a = Inf (TermI a) -- embed an inferrable term
| Lam (Scope() TermC a)
deriving (Functor, Foldable, Traversable)
type Type = TermC -- types are values in a dependent type system
(Iは多かれ少なかれSimply Easyからこれを持ち上げ。)型システムは、その型タイピングコンテキストから推測することができるものに用語を分割、bidirectionalであり、そして唯一の目標に照らしてチェックすることができるものタイプ。従属型システムでは、一般にラムダ項にはプリンシパル型がないため、これは便利です。
とにかく、私はこの構文のためMonad
インスタンスを定義しようとして捕まってしまったしました:
instance Monad TermI where
return = Var
Var x >>= f = f x
App fun arg >>= f = App (fun >>= f) (arg >>= Inf . f) -- embed the substituted TermI into TermC using Inf
Star >>= _ = Star
Pi domain range >>= f = Pi (domain >>= Inf . f) (range >>>= Inf . f)
Ann term ty >>= f = Ann (term >>= Inf . f) (ty >>= Inf . f)
instance Monad TermC where
return = Inf . return
Lam body >>= f = Lam (body >>>= f)
Inf term >>= f = Inf (term >>= _)
をTermC
のインスタンスの最後の行の穴を埋めるために、私はタイプa -> TermI b
の何かを必要とするが、f
タイプはa -> TermC b
です。 TermC
の型がわからないので、結果としてTermC
をTermI
に埋め込むことはできません。Ann
コンストラクタを使用します。
このデータ型はbound
のモデルと互換性がありませんか?または、Monad
インスタンスを作成するために使用できるトリックがありますか?
を持っています'、型システムに構文表現を持たない '(\ x - > x)(var 1)'が得られます。論文中の「subst」の両方には推論可能な用語があり、subst:TermC→TermC→TermC'はありません。双方向型のチェッカーを定義するために必ずしも双方向型のシステムを持つわけではありませんので、これらの相互に再帰的なデータ型を1つの 'Term'にまとめてください。 – user3237465
'bound'は相互データをサポートしていませんが(上記のように)、単一のデータ定義で型チェッカーを実行できます。バインドされたバージョンの索引付きバージョンは相互データ(例:(http://lpaste.net/79582))を実行できますが、発行されたライブラリとしては存在しません。 –
すべてを単一のデータ型に投げることは、面倒なことではないわけではありません。文法上有効ではないアノテーションなしで 'Lam'を書くことができます。私は 'Lam'コンストラクタ(' Lam(Scope()Term a)Type')にタイプを要求することができますが、ネストされたlambdaの余分な注釈を取得し、他の用語に注釈を付けるための追加の構造をサポートしなければなりません。 –