2016-12-28 13 views
10

Dilbilgisi ayrımcı bir birlik olarak tanımlamaya çalışıyorum. İki olası türü vardır: int ve datetime ve Add ve Mul'un matematiksel operatörleri. (Int günlerini eklemek gibi) int ve datetime üzerinde Add eserler Mul sadece int üzerinde çalışır ve bir ayrıştırıcı yazdım F # özyinelemeli ayrımcılığa dayalı sendikalarda tür kısıtlaması nasıl belirtilir

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

gibi datetime üzerinde Dilbilgisi (

Benim dilbilgisi görünüyor özyinelemeli olabilir değil dilbilgisi içinde metni ayrıştırabilen fparsec), ancak Mul'un yalnızca Integer numaralı sürümde yineleyici olabileceği koşulunu nasıl ele alacağımı bilmiyorum.

Bu kısıtlamayı MyExpression türünde tanımlamak için bir seçenek var mı, yoksa ayrıştırılmış girdimde bunu işlemek zorunda mıyım? Eğer tip bazlı kısıtlamaları varsa

cevap

9

tasarımı da benim ilk tercihi olacak. İhtiyaçlarınıza bağlı olarak, ihtiyacınız olan her şey bu olabilir.

Bununla birlikte, aynı zamanda ne istediğinizi muhtemelen olmadığı

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

gibi bir ifade derlemek için izin yok.

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 

Bu açıkça bir daha ayrıntılı tür tanımı, ama bir ifade ya tamsayılar ya DateTime değerlerin yaprak düğümleri içerebilir kuralı somutlaştırmak yapar ve:

Alternatif olarak, böyle ifadeler modeli deneyeyim başka değer yok - eğer zorlamak istediğiniz kural buysa.

Bunun daha iyi olduğunu iddia etmiyorum; Sadece bir alternatif veriyorum.

Kullanımı:

> 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

, bir jenerik yaklaşım için gidiş kolay olabilir:

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) 

Kullanımı: Asti önerdiği

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

Bu kısıtlamaların bazılarını kolları, ama hepsi değil - şu mantıklı bir ifade değil, ama çek yazın: '() Mul Tarih (DateTime.Now ekleyin (Tamsayı 1, Tamsayı 2)) –

İlgili konular