2016-08-29 11 views
1

私は、次のようなデータ構造を持っている:データコンストラクタ制限

IfStatement $ Else ... 
IfStatement $ EndIf 

アン:希望される何

data IfTree = If Expr Statement IfTree | Else Statement | EndIf

data Statement = IfStatement IfTree

は、それが不可能な組み合わせのいずれかを実行するようにすることですIfStatementは、Ifしか使用できません。

私はデータコンストラクタを非表示にすることができ、それらを構成する関数のみを公開することができますが、データ型でこれを制限したいと考えています。

更新:

私が何をしようとしていた何が不格好でした。優れた回答やコメントのおかげで、これを処理するより良い方法が与えられました。

data Statement = If Expr Statement (Maybe Statement) | ...

かさえ:

data Stat = IfStat Expr Stat | IfElseStat Expr Stat Stat | …

答えて

4

のようなものを定義する必要があります。

data Stat = IfStat Expr Stat (Maybe Stat) | BarStat | BazStat | … 
data Expr = FooExpr | … 

-- if (foo) bar; 
IfStat FooExpr BarStat Nothing 

-- if (foo) bar; else baz; 
IfStat FooExpr BarStat (Just BazStat) 

アイデアは、データ型として使用する言語の文法を符号化することである、または少なくとも重要なビット。 ElseEndIfIfの外で意味をなさないので、実際に表現する必要はありません。

あなたは文のデータ型にMaybeをインライン化することができます、しかし

data Stat = IfStat Expr Stat Stat | EmptyStat | … 

-- if (foo) bar; 
-- if (foo) bar; else; 
IfStat FooExpr BarStat EmptyStat 

-- if (foo) bar; else baz; 
IfStat FooExpr BarStat BazStat 

data Stat = IfStat Expr Stat | IfElseStat Expr Stat Stat | … 

それとも、それはあなたの言語のために理にかなっている場合、あなたは空の文の表現を追加することができますこのようなことを正規化することは、あとで正確なかわいい印刷をしたい場合には問題になります。

ブロック文を同様に扱うことができる。

data Stat = … | BlockStat [Stat] | … 

-- if (foo) { bar; baz; } 
IfStat FooExpr (BlockStat [BarStat, BazStat]) EmptyStat 
+1

これは、@DanielWagnerが上記でコメントしたことをエコーし​​ます。しかし、あなたは最初に答えを正式化したので、あなたの答えを正しいものとしてマークします。優秀な提案をありがとう! – kurzweil4

+0

これを見てから、IfStat/IfElseStatが最もエレガントであると思う。 – kurzweil4

2

問題はIfではないということですただElseです。あなたは、これはそれを行うの伝統的な方法だろう

data If = IfNoElse Expr Statement | IfElse Expr Statement Statement 
data Statement = If If | While | ... 
+0

IF(COND){}他{}} {もしそう= 'ES場合 ' – kurzweil4

+0

IF(E」S'(エルスS '')の場合) (cond){} = 'If End If ' – kurzweil4

+0

@ kurzweil4もちろん可能です。 if(ifElse cond 's' '))) 'if(ifElse cond' s) ')'になります。 –