2016-12-28 4 views
10

私は識別された共用体として私の文法を定義しようとしています。これには、intdatetimeという2つのタイプと、AddMulという数学演算子の2つのタイプがあります。 (int型に日追加など)intdatetimeAdd作品 Mul作品のみdatetimeintないで文法がF#再帰的に識別される共用体の型制限を指定する方法

再帰的にすることができ私の文法は、私が(パーサを書かれている

type MyExpression = 
|Integer of int 
|Date of datetime 
|Add of MyExpression * MyExpression 
|Mul of MyExpression * MyExpression 

のように見えます私の文法でテキストを解析することができますが、私はMulが再帰的であるが、Integerのみであるという条件をどのように処理するかはわかりません。

私のMyExpressionタイプでこの制限を定義するオプションはありますか、これを解析された入力で処理する必要がありますか?あなたがタイプベースの制約がある場合は

答えて

9

アスティによって提案されたデザインも私の最初の選択です。要件に応じて、それだけで十分です。

それは、しかし、また、あなたが望むものはおそらくない

Add(Val(System.Console.Out), Val(System.Console.Error)) 

のような表現をコンパイルすることができますありません。

また、あなたはこのような表現をモデル化することができます:

open System 

type IntExpression = 
| Integer of int 
| Mul of IntExpression * IntExpression 
| Add of IntExpression * IntExpression 

type DateTimeExpression = 
| Date of DateTime 
| Add of DateTimeExpression * DateTimeExpression 

type MyExpression = 
| IntExpression of IntExpression 
| DateTimeExpression of DateTimeExpression 

これは明らかに、より詳細な型定義であるが、それは式が整数またはDateTime値のいずれかのリーフ・ノードを含むことができ、ルールを具現化し、そしてそれ以外の値はありません - もしそれがあなたが強制したいルールなら。

私はこれがより良いと主張していません。私は代わりを提供しているだけです。

使用法:

> IntExpression(Mul(IntExpression.Add(Integer(1), Integer(2)),Integer 3));; 
val it : MyExpression = 
    IntExpression (Mul (Add (Integer 1,Integer 2),Integer 3)) 
> DateTimeExpression(Add(Date(DateTime.MinValue),Date(DateTime.MinValue)));; 
val it : MyExpression = 
    DateTimeExpression 
    (Add 
     (Date 01.01.0001 00:00:00 {Date = 01.01.0001 00:00:00; 
            Day = 1; 
            DayOfWeek = Monday; 
            DayOfYear = 1; 
            Hour = 0; 
            Kind = Unspecified; 
            Millisecond = 0; 
            Minute = 0; 
            Month = 1; 
            Second = 0; 
            Ticks = 0L; 
            TimeOfDay = 00:00:00; 
            Year = 1;}, 
     Date 01.01.0001 00:00:00 {Date = 01.01.0001 00:00:00; 
            Day = 1; 
            DayOfWeek = Monday; 
            DayOfYear = 1; 
            Hour = 0; 
            Kind = Unspecified; 
            Millisecond = 0; 
            Minute = 0; 
            Month = 1; 
            Second = 0; 
            Ticks = 0L; 
            TimeOfDay = 00:00:00; 
            Year = 1;})) 
7

、それは一般的なアプローチのために行く方が簡単な場合があり:

type MyExpression<'t> = 
|Val of 't 
|Mul of MyExpression<int> * MyExpression<int> 
|Add of MyExpression<'t> * MyExpression<'t> 

let Integer (x:int) = Val(x) 
let Date (x:DateTime) = Val(x) 

使用法:

Mul(Integer(1), Integer(2)) //compiles 
Mul(Date(DateTime.Now), Date(DateTime.Now)) //error 
+1

これは、制限の一部を処理し、それらのすべてではない - 次は賢明な表現ではありませんが、それはチェックを入力します ')(ムルを日付(DateTime.Nowを追加します(整数1、整数2)) ' –

関連する問題