2016-12-28 2 views
10

차별화 된 공용체로서 내 문법을 정의하려고합니다. 가능한 유형은 intdatetime이며 AddMul의 수학 연산자가 있습니다. (INT에서 일 추가로) intdatetimeAdd 작품 Mulint에서 작동 내가 파서를 작성했습니다 F # 재귀 식별 된 유니온에서 유형 제한을 지정하는 방법

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

처럼 datetime 에 문법 (

내 문법 보이는 재귀가 될 수 없습니다 fparsec) 문법에서 텍스트를 구문 분석 할 수 있지만, 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))' –