2016-08-29 3 views
1

У меня есть структуры данных как таковой:данных Конструктор Ограничения

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

data Statement = IfStatement IfTree

Что хотят, чтобы сделать это невозможно сделать какие-либо из этих комбинаций:

IfStatement $ Else ... 
IfStatement $ EndIf 

An IfStatement должен принимать только If.

Я знаю, что я могу скрыть конструкторы данных и только выставлять функции, которые составляют их за кулисами, но я хочу ограничить это по типу данных.

Update:

То, что я пытался сделать, было неуклюжим. Благодаря отличному ответы и комментарии, гораздо лучший способ обращения с этим было дано:

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) 

Идея заключается в том, чтобы кодировать грамматику своего языка как тип данных, или, по крайней мере, важные биты , Else и EndIf не имеют смысла за пределами If, поэтому вам фактически не нужно их представлять.

Вы можете встраивать в Maybe в тип утверждение данных:

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

Или, если это имеет смысл для вашего языка, вы можете добавить представление для пустых заявлений:

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 = … | 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

если (условие) {} иначе, если {} еще {} = 'Если ы (если е» с (остальное с '')) ' – kurzweil4

+0

, если (cond) {} ​​= 'If es EndIf' – kurzweil4

+0

@ kurzweil4 Конечно, вы можете. 'if (cond) {s} else if (cond ') {s'} else {s ''}' становится 'If (IfElse cond s (If (IfElse cond 's' ')))'. –

Смежные вопросы