繁体   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