2013-03-15 19 views
1

我試圖在使用parsec庫的haskell中實現語法,但我遇到了預期比較問題。在語法中定義的實際類型,我知道我的問題的答案無疑是簡單/明顯的,但唉,有一些我不明白...具有數據定義的haskell中的語法問題

數據聲明的摘錄如下(應該足以診斷):

data Expr1 = SeqOfExpr1 [Expr1] 
      | Lambda Expr8 Expr1 
      | List Expr2 Expr1 
      | If Expr2 Expr1 Expr1 
      | Expr2 
       deriving (Show) 

data Expr2 = SeqOfExpr3 [Expr3] 
       deriving (Show) 

data Expr3 = SeqOfExpr4 [Expr4] 
       deriving (Show) 
----------------------------Redundant Code Omitted------------------------------ 
expr1 :: Parser Expr1 
expr1 = declaration 
     <|> list 
     <|> ifStmt 
     <|> expr2 

declaration :: Parser Expr1 
declaration = 
    do reservedOp "\\" 
     var <- name 
     reservedOp "->" 
     expr <- expr1 
     return $ Lambda var expr 

list :: Parser Expr1  
list = 
    do exprA <- expr2 
     reservedOp ":" 
     exprB <- expr1 
     return $ List exprA exprB 

現在有用於表達進一步的數據申報到用expr8但他們是一樣一樣的表達式2 - >表達式3它們之間的不同之處在於他們是如何界定如表達式3的用「||」分隔,Expr4的由「& &」等

一個我遇到的問題(這要是解決應該提供我的想法來解決其餘部分):

列表值構造返回表達式1導致衝突:

Couldn't match expected type `Expr2' with actual type `Expr1' 
In the first argument of `List', namely `exprA' 
In the second argument of `($)', namely `List exprA exprB' 
In a stmt of a 'do' block: return $ List exprA exprB 

我想這是因爲我使用EXPR2作爲表達式1的值的聲明,但是我不知道如何糾正語法來解決這個問題。

在此先感謝您的幫助!

肖恩

+2

爲什麼你需要所有這些'Expr '數據類型?爲什麼不把它們解析爲簡單的'Expr',然後應用類型檢查? – pat 2013-03-15 16:47:31

+1

它甚至不像是一個類型檢查的問題。如果由於運算符優先級引入了多個表達式*解析器*,那麼您仍然不一定需要引入多個表達式數據類型,就像在抽象語法中一樣,運算符優先級無論如何都是完全明確的。所以你可以有'expr '分析器函數,它們都返回一個'Expr'結果。 – kosmikus 2013-03-15 19:19:55

回答

5

data Expr1,你有一個null構造Expr2。我懷疑你的意思是

data Expr1 = 
      ... 
      | Foo Expr2 

包裝Expr2

無論如何,每

expr1 :: Parser Expr1 
expr1 = declaration 
     <|> list 
     <|> ifStmt 
     <|> expr2 

編譯器推斷expr2 :: Parser Expr1,但是當你嘗試

list :: Parser Expr1  
list = 
    do exprA <- expr2 
     reservedOp ":" 
     exprB <- expr1 
     return $ List exprA exprB 

List的類型意味着exprA必須是Expr2,但是從expr2的類型,編譯器知道exprA :: Expr1

所以你可能需要包裝expr2list

list = ... 
    <|> fmap Foo expr2 

如果你改變的Expr1定義,包括一個Foo構造函數來包裝一個Expr2