2010-12-10 27 views
7

Şu anda bir ifade ayrıştırıcısı yazıyorum. Sözlüksel ve sözdizimsel analizleri yaptım ve şimdi türleri kontrol ediyorum. Bu (basitleştirilmiş sürümü) gibi bir veri structire ifadeyi vardır:Yeni bir tür tanıtacak bir Haskell işlevi nasıl oluşturulur?

data Expr = EBinaryOp String Expr Expr 
      | EInt Int 
      | EFloat Float 

Ve şimdi yeni bir türle dönüştürmek verecek bir işlev gerekir, ayrıca tip bilgiler içerecektir hangi TypedExpr söylüyorlar. Ve şimdi asıl problemim, bu tip nasıl görünmelidir. İki fikirleri var - tipi parametresi ile:

data TypedExpr t = TEBinaryOp (TBinaryOp a b t) (TExpr a) (TExpr b) 
       | TEConstant t 
addTypes :: (ExprType t) => Expr -> TypedExpr t 

veya olmadan:

data TypedExpr = TEBinaryOp Type BinaryOp TypedExpr TypedExpr 
       | TEConstant Type Dynamic 
addTypes :: Expr -> TypedExpr 
Ben ilk seçeneği ile başladı

, ancak bu yaklaşım ifadenin türünü bildiğiniz varsayılmaktadır çünkü sorunlarla karşılaştı ayrıştırmadan önce (benim için çoğu durumda doğrudur, ama her zaman değil). Bununla birlikte, bunu sevdim, çünkü Haskell'in tip sistemini kullanmam ve derleme zamanında çoğu hatayı kontrol etmeme izin veriyor.

ilk seçeneği ile bunu yapmak mümkün mü?
Hangisini seçersiniz? Niye ya?
Her seçenekte hangi sorunları beklemeliyim? çalışma zamanında ayrıştırılmasını yapıyoruz yana

cevap

10

sizin fonksiyonu

addTypes :: Expr -> TypedExpr t 

tipi size gibi herhangi t için TypedExpr talmak, yanlıştır. Buna karşılık, gerçekte ne istediğini tip Expr argümanı ile belirlenir belirli birt olduğunu.

zaten bu muhakeme

Eğer Hindley'nin-Milner tipi sisteminin yetenekleri ötesinde olduğunu göstermektedir. Sonuçta, dönüş tipiaddTypes ait Tartışmanın değeri bağlı olmalıdır, ama düz Haskell 2010'da, türleri değerlere bağlı olmayabilir. Bu nedenle, bağımlı türleri'a daha yakın hale getiren tür sisteminin bir uzantısına ihtiyacınız vardır. Haskell'de genelleştirilmiş cebirsel veri tipleri (GADTs) yapabilir. GADTs bir tanıtımı için

, ayrıca my video on GADTs görüyoruz. Ancak, GADT'leri tanıdıktan sonra, yazılmamış bir ifadeyi yazılan bir taneye ayrıştırma sorununa hala sahip olursunuz, örn.Bir fonksiyonu Tabii

addTypes :: Expr -> (exists t. TypedExpr t) 

yazmak için, kendini kontrol çeşit gerçekleştirmek zorunda, ama durumda bile, (değer düzeyde gerçekleşmesi) senin tipin kontrolleri olabilir Haskell derleyicisi ikna etmek kolay değildir tip seviyesine kaldırıldı.

Edward Kmett: Neyse ki, diğer insanlar zaten haskell-cafe posta listesindeki örneğin aşağıdaki iletiyi bakın bu konuda düşündüm.
Re: Manual Type-GADT'ler için Read örnekleri sağlamayı denetleme. (Re edildi: [Haskell-cafe] GATD için örnek Oku)
http://article.gmane.org/gmane.comp.lang.haskell.cafe/76466

(herkes resmen yayınlanmış/güzel kadar yazılı başvuru biliyor mu?)

3

, derleme süresi değil, sen (siz ilgili modülleri içe ve sürece elle kendin diyoruz.) Haskell'ın tip sisteminin kapalı domuz geri edemez

Sen isteyebilirsiniz İlham almak için basit bir lambda hesabı için TAPL'in ML tipi tipli damağa dönüşmesi. http://www.cis.upenn.edu/~bcpierce/tapl/ (uygulamalar altında). Lambdaları desteklemediğinizden, ifade ayrıştırıcınızdan biraz daha fazlasını yaparlar. bunun anlamı, çünkü

4

Geçenlerde için tagless-final syntax kullanmaya başladılar gömülü DSL'leri ve standart GADT yönteminden çok daha iyi olduğunu buldum (ki buna yöneliyorsunuz ve Apfelmus açıklıyor).

Etiketsiz final sözdiziminin anahtarı, bir ifade veri türü kullanmak yerine, bir tür sınıfıyla işlemleri temsil ettiğidir. Ayrı BinaryOp işlevlerini yapmak yerine olsa bir Dize kullanacağı

class Repr repr where 
    eInt :: repr Int 
    eFloat :: repr Float 

class Repr repr => BinaryOp repr a b c where 
    eBinaryOp :: String -> repr a -> repr b -> repr c 

: En eBinaryOp gibi işlevler için İki sınıf kullanabilmesidir iyi buldum. Haskell'in tip sistemini kullanan bir ayrıştırıcı dahil olmak üzere Oleg's web page hakkında daha fazla bilgi var.

+0

Vay canına! ilginç fikir. Bunu asla düşünmüyorum :) – mik01aj

+0

Sanırım çözümünüzü çok iyi anlayamıyorum - "eInt", "eBinaryOp" ne yapmalı? Expr'imi bu modele nereye koyacağım? – mik01aj

İlgili konular