[英]Haskell pattern matching error with data constructor
我在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:錯誤:•無法將類型'StmtT'與'[ProgT]'匹配預期類型:[ProgT]實際類型:ProgT•在'(:)'的第二個參數中,即'changeName xy(Seq moreStatements)'在'Seq'的第一個參數中,即'(changeName xy oneStatement:changeName xy(Seq moreStatements))'在表達式中:Seq(changeName xy oneStatement:changeName xy(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使用地圖有助於解決該錯誤(因為該函數現在不返回列表)。
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 xy Seq(moreStatements)
的最后一部分被視為將changeName
應用於4個參數:
x
y
Seq
(moreStatements)
Seq(moreStatements)
並不意味着“將Seq
應用於moreStatements
,就像在使用類似於C的語法的語言中那樣,而只是術語Seq
(moreStatements)
彼此相鄰,完全等同於您是否編寫了Seq moreStatements
因為Seq
是該子表達式的“頭”,所以它可以做您想要的事情,但是它跟隨在changeName xy
,因此將其應用於Seq
,然后應用於moreStatements
。這不適合changeName
的類型。
(請注意,這幾乎完全是錯誤消息所說的內容)
您的第二個錯誤是changeNames
類型為String -> String -> ProgT -> ProgT
(記住ProgT = StmtT
)。 但是,您使用的結果changeName
上的右側:
,仿佛它返回的東西的清單 。
可能您需要改為在列表上changeName
名稱,而不是將其應用於頭部和尾部? 實際上,您甚至不需要在列表上進行模式匹配,您可以:
changeName x y (Seq statements) = Seq (map (changeName x y) statements)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.