简体   繁体   English

数据构造函数的Haskell模式匹配错误

[英]Haskell pattern matching error with data constructor

I have the following code in 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))

The definition of ProgT is defined in the module SImpL: 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 

Put simply, Seq[StmtT] is a list of Assign, If or While statements defined in the constructor. 简单地说,Seq [StmtT]是在构造函数中定义的Assign,If或While语句的列表。 The function changeName checks if there are variables in ALL statements that equal to x, and replaces it with y. 函数changeName检查ALL语句中是否存在等于x的变量,并将其替换为y。 When I run the code, I get the following error: 运行代码时,出现以下错误:

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 xy (Seq moreStatements)' In the first argument of 'Seq', namely '(changeName xy oneStatement : changeName xy (Seq moreStatements))' In the expression: Seq (changeName xy oneStatement : changeName xy (Seq moreStatements)) 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))

Based on the error message, the problem is in the last line: 根据错误消息,问题在最后一行:

changeName xy (Seq (oneStatement:moreStatements)) = Seq(changeName xy oneStatement: changeName xy (Seq moreStatements) ) changeName xy(Seq(oneStatement:moreStatements))= Seq(changeName xy oneStatement: changeName xy(Seq moreStatements)

I can see why it would throw the error, but I have to recurse through each statement to change every variable in the statements. 我可以理解为什么会引发错误,但是我必须遍历每个语句来更改语句中的每个变量。 Apologies if this is trivial, but I don't know I could recurse through Seq[StmtT] types without the error. 抱歉,这很简单,但是我不知道我可以通过Seq [StmtT]类型进行递归而不会出现错误。

note: I don't think it matters what the other data types are (ie BExprT), just in case here is more of the module: 注意:我不认为其他数据类型是什么(即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)]

EDIT: @Ben Using map helped get around the error (since the function does not return a list now). 编辑: @Ben使用地图有助于解决该错误(因为该函数现在不返回列表)。

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

Should be: 应该:

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

Specifically the problem is that the last part where you have changeName xy Seq(moreStatements) is seen as applying changeName to 4 arguments: 具体来说,问题在于您拥有changeName xy Seq(moreStatements)的最后一部分被视为将changeName应用于4个参数:

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

Seq(moreStatements) doesn't mean "apply Seq to moreStatements , as it would in a language with C-like syntax, but is rather just the terms Seq (moreStatements) next to each other, completely equivalent to if you had written Seq moreStatements because the parentheses are not needed to group a single identifier. If Seq was the "head" of that sub-expression it would do what you want, but it follows on changeName xy , so that is applied to Seq , and then to moreStatements , which doesn't fit the type of changeName . Seq(moreStatements)并不意味着“将Seq应用于moreStatements ,就像在使用类似于C的语法的语言中那样,而只是术语Seq (moreStatements)彼此相邻,完全等同于您是否编写了Seq moreStatements因为Seq是该子表达式的“头”,所以它可以做您想要的事情,但是它跟随在changeName xy ,因此将其应用于Seq ,然后应用于moreStatements 。这不适合changeName的类型。

(Note that this is pretty much exactly what the error message said) (请注意,这几乎完全是错误消息所说的内容)


Your second error is that changeNames has type String -> String -> ProgT -> ProgT (and remember ProgT = StmtT ). 您的第二个错误是changeNames类型为String -> String -> ProgT -> ProgT (记住ProgT = StmtT )。 But you use the result of changeName on the right side of : , as if it returned a list of something. 但是,您使用的结果changeName上的右侧: ,仿佛它返回的东西的清单

Probably you need to instead changeName over the list, rather than applying it to the head and to the tail? 可能您需要改为在列表上changeName名称,而不是将其应用于头部和尾部? In fact you wouldn't even need to pattern match on the list then, you could just: 实际上,您甚至不需要在列表上进行模式匹配,您可以:

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