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

时间:2017-03-14 02:30:20

标签: 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:错误:       •无法将类型'StmtT'与'[ProgT]'匹配         预期类型:[ProgT]           实际类型:ProgT       •在'(:)'的第二个参数中,即           'changeName x y(Seq moreStatements)'         在'Seq'的第一个参数中,即           '(changeName x y oneStatement             :changeName x y(Seq 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)

我可以看出它为什么会抛出错误,但是我必须通过每个语句递归来改变语句中的每个变量。抱歉,如果这是微不足道的,但我不知道我可以通过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使用map帮助解决错误(因为该函数现在不返回列表)。

1 个答案:

答案 0 :(得分: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)
  5. Seq(moreStatements)并不意味着"将Seq应用于moreStatements,就像使用类似C语法的语言一样,但仅仅是Seq {1}} (moreStatements)彼此相邻,完全等同于您编写Seq moreStatements,因为不需要括号来对单个标识符进行分组。如果Seq是" head"该子表达式可以执行您想要的操作,但它会在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) 而不是将它应用到头部和尾部?事实上,你甚至不需要在列表上进行模式匹配,你可以这样做:

    https://www.google.com