重新格式化Haskell数据构造函数类型程序并重新格式化它

时间:2017-03-13 23:19:40

标签: haskell

我们在SImpL.hs文件中给出了代码,其中包含以下数据构造函数和类型:

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)]

我们被要求完成这项任务:

  

编写一个名为changeName的函数,它将采用一个SImpL程序(a   stmtT类型的值)并返回此程序的副本   变量名称已更改。这个函数应该有三个参数:   两个字符串和一个SImpL程序。字符串代表变量   名。您的函数应该返回所有程序的副本   第一个字符串的实例被第二个字符串替换。对于   例如,如果myProgram表示这一点,则使用类似Java的表示法   程序:

x = 3
y = 14
z = 0
while (x < y)
   z = z + x*y
   x = x + 1
answer = z + y
  

changeName&#34; x&#34;的结果&#34;数&#34; myProgram应该是一个   该计划的代表:

number = 3
y = 14
z = 0
while (number  < y)
    z = z + number *y
    number = number  + 1
answer = z + y
  

你的changeName函数需要为每种类型都有一个案例   在SImpL语言中的语句,您将需要一个辅助函数   更改表达式中变量的名称。

我所做的伪代码如下:

module Assignment3 where

import SImpL

changeName :: String -> String -> StmtT -> StmtT
changeName val1 val2 (Assign NameT AExprT) = ...
changeName val1 val2 (If BExprT StmtT StmtT) = ...
changeName val1 val2 (While BExprT StmtT) = ...
changeName val1 val2 (Seq [StmtT]) = ...

虽然我认为我理解了这个的基本要点,但我对代码的实际实现感到很遗憾。例如,如果您运行此代码:

changeName "x" "num" testMyProgram...

其中testMyProgram只是

Assign "x" (ALit 3)

我不知道如何让Haskell返回一行StmtT代码,例如:

Assign "num" (ALit 3)

我很确定这是指导者想要的指示。

1 个答案:

答案 0 :(得分:2)

您需要创建一个解构术语的函数,如果其中一个组件需要替换,则构造一个新术语。

changeNameStmt x y (Assign a b) | x == a = Assign y (changeNameExpr x y b)
                                | otherwise = Assign a (changeNameExpr x y b)
...

由于Expr也可能引用变量,因此有必要递归到它并替换那里出现的所有事件。

changeNameExpr x y (Name n) | x == n = Name y
...
changeNameExpr x y (Add a b) = Add (changeNameExpr x y a) (changeNameExpr x y b)

对语句中涉及的所有类型执行此操作。如果你想要一个多态changeName,你可以定义一个类并创建它的类型实例。