2017-03-14 69 views
0

我在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: error: • Couldn't match type ‘StmtT’ with ‘[ProgT]’ Expected type: [ProgT] Actual type: ProgT • In the second argument of ‘(:)’, namely ‘changeName x y (Seq moreStatements)’ In the first argument of ‘Seq’, namely ‘(changeName x y oneStatement : changeName x y (Seq moreStatements))’ In the expression: Seq (changeName x y oneStatement : changeName x y (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使用地图帮助解决了错误(因为函数现在不返回列表)。

回答

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)

Seq(moreStatements)并不意味着“适用于SeqmoreStatements,因为它会在与类似C的语法语言,相反却是正好条款Seq(moreStatements)彼此相邻,完全等同于如果你写了Seq moreStatements,因为不需要括号来分组一个标识符。如果Seq是该子表达式的“头部”,它将按照您的要求进行操作,但它随后出现在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) 
+0

谢谢你,但我仍然会碰到一个错误,当我改变了括号,即这样的:不能匹配类型 'StmtT' 与 '[ProgT]' 预期类型:[ProgT] 实际类型:ProgT •在的第二个参数 '(:)',即 'changeName XY(SEQ moreStatements)' –

+0

@RosaryLightningX I”我编辑了我的答案,以解决这个问题,尽管它在技术上是一个完全独立的错误,只是被第一个错误所掩盖。 – Ben

+0

啊,是的,改变方法肯定有帮助 - 现在模式匹配正确编译。我根本没有考虑过使用地图和头部和尾部,非常感谢你的洞察力。 –