2017-03-14 94 views
0

我在Haskell以下代碼:Haskell的模式匹配誤差

module testData where 

import SImpL 
changeName :: String -> String -> ProgT -> ProgT 
... 
changeName x y (Seq []) = Seq[] 
changeName x y (Seq (oneStatement:moreStatements)) = Seq (changeName x y oneStatement : changeName x y (Seq moreStatements)) 

ProgT的定義模塊中定義的SIMPL:

data StmtT = Assign NameT AExprT | 
      If BExprT StmtT StmtT | 
      While BExprT StmtT | 
      Seq [StmtT] -- If the list is empty, this is a statement that does nothing.  
      deriving (Show,Eq) 

type ProgT = StmtT 

簡而言之,SEQ [StmtT]是在構造函數中定義的Assign,If或While語句的列表。 函數changeName檢查ALL語句中是否有等於x的變量,並用y替換它。當我運行該代碼時,得到下面的錯誤:

Assignment3.hs:12:89: error: • Couldn't match type ‘StmtT’ with ‘[ProgT]’ Expected type: [ProgT] Actual type: ProgT • In the second argument of ‘(:)’, namely ‘changeName x y (Seq moreStatements)’ In the first argument of ‘Seq’, namely ‘(changeName x y oneStatement : changeName x y (Seq moreStatements))’ In the expression: Seq (changeName x y oneStatement : changeName x y (Seq moreStatements))

基於該錯誤消息,問題是在最後一行:

changeName XY(SEQ(oneStatement:moreStatements))= SEQ(changeName XY oneStatement:changeName XY(SEQ moreStatements)

我可以看到爲什麼它會拋出錯誤,但我必須通過每個語句改乘改變每個變量的聲明。道歉,如果這是微不足道的,但我不知道我可以遞歸通過Seq [StmtT]類型沒有錯誤。

注:我不認爲這有什麼重要的其他數據類型(即BExprT),以防萬一這裏是更多的模塊:

module SImpL where 

data AExprT = ALit ValT -- a literal value (an Int) 
       | AName NameT -- a variable name (a String) 
       | Add AExprT AExprT -- one arithmetic expression added to another 
       | Sub AExprT AExprT -- one arithmetic expression subtracted from another 
       | Mult AExprT AExprT -- one arithmetic expression multiplied by another 
       deriving (Show,Eq) 

data BExprT = BLit Bool -- a literal value (True or False) 
       | Eq AExprT AExprT -- an equality test between two arithmetic expressions 
       | Less AExprT AExprT -- a "less than" test between two arithmetic expressions 
       | Greater AExprT AExprT -- a "greater than" test between two arithmetic expressions 
       | Not BExprT -- the negation of a boolean expression 
       | And BExprT BExprT -- the "and" of two boolean expressions 
       | Or BExprT BExprT -- the "or" of two boolean expressions 
       deriving (Show,Eq) 

type ValT = Integer 

type NameT = String 

data StmtT = Assign NameT AExprT | 
      If BExprT StmtT StmtT | 
      While BExprT StmtT | 
      Seq [StmtT] -- If the list is empty, this is a statement that does nothing.  
      deriving (Show,Eq) 

If BExprT StmtT StmtT | 
      While BExprT StmtT | 
      Seq [StmtT] -- If the list is empty, this is a statement that does nothing.  
      deriving (Show,Eq) 

type ProgT = StmtT 

type StateT = [(NameT, ValT)] 

編輯: @Ben使用地圖幫助解決了錯誤(因爲函數現在不返回列表)。

回答

1
changeName x y (Seq (oneStatement:moreStatements)) = Seq(changeName x y oneStatement:changeName x y Seq(moreStatements)) 

應該是:

changeName x y (Seq (oneStatement:moreStatements)) = Seq (changeName x y oneStatement : changeName x y (Seq moreStatements)) 

具體的問題是,你必須changeName x y Seq(moreStatements)最後一部分被視爲應用changeName到4個參數:

  1. x
  2. y
  3. Seq
  4. (moreStatements)

Seq(moreStatements)並不意味着「適用於SeqmoreStatements,因爲它會在與類似C的語法語言,相反卻是正好條款Seq(moreStatements)彼此相鄰,完全等同於如果你寫了Seq moreStatements,因爲不需要括號來分組一個標識符。如果Seq是該子表達式的「頭部」,它將按照您的要求進行操作,但它隨後出現在changeName x y之後,因此適用於Seq,然後是moreStatements,這不適用於changeName的類型。

(注意,這是非常準確的錯誤消息說的話)


你的第二個錯誤是,changeNames具有類型String -> String -> ProgT -> ProgT(記住ProgT = StmtT)。但是您在:的右側使用changeName的結果,就好像它返回了某個列表的東西。

也許你需要在列表上代替changeName,而不是將它應用到頭部和尾部?事實上,你甚至不需要到列表上的圖案匹配,那麼,你可以只:

changeName x y (Seq statements) = Seq (map (changeName x y) statements) 
+0

謝謝你,但我仍然會碰到一個錯誤,當我改變了括號,即這樣的:不能匹配類型 'StmtT' 與 '[ProgT]' 預期類型:[ProgT] 實際類型:ProgT •在的第二個參數 '(:)',即 'changeName XY(SEQ moreStatements)' –

+0

@RosaryLightningX I」我編輯了我的答案,以解決這個問題,儘管它在技術上是一個完全獨立的錯誤,只是被第一個錯誤所掩蓋。 – Ben

+0

啊,是的,改變方法肯定有幫助 - 現在模式匹配正確編譯。我根本沒有考慮過使用地圖和頭部和尾部,非常感謝你的洞察力。 –