2016-08-20 9 views
6

次は、依存型のラムダ計算の構文です。バウンドを使用した相互再帰構文

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の型がわからないので、結果としてTermCTermIに埋め込むことはできません。Annコンストラクタを使用します。

このデータ型はboundのモデルと互換性がありませんか?または、Monadインスタンスを作成するために使用できるトリックがありますか?

+0

を持っています'、型システムに構文表現を持たない '(\ x - > x)(var 1)'が得られます。論文中の「subst」の両方には推論可能な用語があり、subst:TermC→TermC→TermC'はありません。双方向型のチェッカーを定義するために必ずしも双方向型のシステムを持つわけではありませんので、これらの相互に再帰的なデータ型を1つの 'Term'にまとめてください。 – user3237465

+1

'bound'は相互データをサポートしていませんが(上記のように)、単一のデータ定義で型チェッカーを実行できます。バインドされたバージョンの索引付きバージョンは相互データ(例:(http://lpaste.net/79582))を実行できますが、発行されたライブラリとしては存在しません。 –

+0

すべてを単一のデータ型に投げることは、面倒なことではないわけではありません。文法上有効ではないアノテーションなしで 'Lam'を書くことができます。私は 'Lam'コンストラクタ(' Lam(Scope()Term a)Type')にタイプを要求することができますが、ネストされたlambdaの余分な注釈を取得し、他の用語に注釈を付けるための追加の構造をサポートしなければなりません。 –

答えて

2

これは非常に単純に不可能です。TermCはモナドではありません。置換は変数の代わりに用語を置きます。これが意味を成すためには、用語は適合することができなければならない。すなわち、得られる用語が依然として良好な特性を有するように十分に類似である必要がある。ここでは、そのタイプが推測可能でなければならないことを意味します。 TermCはしません。

あなたは、実装することができ、次のいずれか[\ X - > X]

substI :: TermI a -> (a -> TermI b) -> TermI b 
substC :: TermC a -> (a -> TermI b) -> TermC b 

を、あなたは(表記を乱用) `(VAR 0(VAR 1))を実行した場合

instance Monad TermI where 
    return = Var 
    bind = substI 
+0

このように動作します - あなたは 'Monad'インスタンスを取得しますが、それは醜いものに終わります。大部分のバインドされたコンビネータ( 'Scope'の下に 'fmap'pingで' subst 'を実装する必要があります)を使うことはできません。スコープの2番目のパラメータです。だから、あなたは結局、縛られたものの大部分を再実装することになります。 –

関連する問題