2015-08-24 10 views
10

Quindi voglio un tipo che rappresenti alberi contenenti un insieme di tipi di nodi. Mi piacerebbe anche i tipi che rappresentano un albero simile definito su insiemi sovrapposti. Questa è un'altra versione del problema AST digitato. Dire che il mio pool di nodi tipi è:Come posso ridurre l'ingombro sintattico quando taggano un albero polimorfico in Haskell?

data Lit = Lit Int 
data Var = Var String 
data Hole = Hole Int 

Un parse-albero può contenere Lit s o Var s ma non Hole s. Un secondo albero gentile chiamato modello può contenere Lit s, Var s o Hole s.

Per semplificare le cose, esiste un singolo tipo di nodo ricorsivo chiamato Add.

data Parse = A Lit | B Var 
data Template = C Lit | D Var | E Hole 
data Tree a = Leaf a 
      | Add (Tree a) (Tree a) 

Così ora può dichiarare dei dati, e posso ancora pattern-partita su di esso, l'unico problema è il disordine sintattico.

aParse = Add (A Lit 3) (B Var "x") 
aTemplate = Add (C Lit 4) (E Hole 3) 
fun (Add (A lit) (B var) = ... 

Quello che vorrei è un po 'di zucchero simile a:

ParseLit = A . Lit 
TempLit = C . Lit 

uno pseudonimo Ovviamente per composizioni di costruttori (non tipi) non è legale in Haskell. Ma qual è il modo più pulito per scrivere questo, evitando il maggior numero possibile di piastre della caldaia?

risposta

14

L'estensione della lingua PatternSynonyms può essere d'aiuto. Esso consente di specificare alias per i modelli:

{-# LANGUAGE PatternSynonyms #-} 

pattern ParseLit x = A (Lit x) 

someFunc :: Parse -> Int 
someFunc p = case p of 
    ParseLit x -> x 
    _ -> 0 

Ci sono due tipi di sinonimi modello: bidirezionali (come nell'esempio) e unidirezionali. Quelli bidirezionali possono anche essere utilizzati come costruttori:

*Main> :t ParseLit 
ParseLit :: Int -> Parse 

*Main> ParseLit 77 
+0

Oh wow. Questo è esattamente quello che stavo cercando. Grazie. – Amoss

Problemi correlati