簡體   English   中英

數據構造函數的Haskell模式匹配錯誤

[英]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個參數:

  1. x
  2. y
  3. Seq
  4. (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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM