将自定义数据类型转换为字符串

时间:2017-10-09 16:12:57

标签: haskell

如果我有三种名为ExprOpFu的数据类型,请执行此操作。

data Expr = Num Double
          | X
          | Operator Op Expr Expr
          | Function Fu Expr
          deriving (Eq)

data Op = Add | Mul
        deriving (Eq)

data Fu = Sin | Cos
        deriving (Eq)

我应该做的是稍后根据数据类型创建表达式。例如

let anExpr = Add (Num 3.0) (Num 4.0)

然后打印出相应的表达式,在这种情况下它应该只是“3.0 + 4.0”。

我面临的问题是创建另一种类型或数据类型,以识别它是否应该打印出来的加法或乘法符号。我想做的是伪代码

这样的事情
printOut (Num n) = show n
printOut X = "x"
printOut (Op a b) = printOut a ++ 'printOutRightOp' ++ printOut b
printOut (Fu a) = 'printOutRightFu' ++ printOut a

我该怎么做?

2 个答案:

答案 0 :(得分:5)

无法将对类型的引用写为构造函数名称。在您的代码中:

data Expr = Num Double
          | X
          | Op Expr Expr
          | Fu Expr
          deriving (Eq)

OpFu是构造函数的名称。 Haskell认为存在一个具有相同名称的类型,只是巧合。您必须添加运算符/函数的类型作为第一个参数。所以:

data Expr = Num Double
          | X
          | Op Op Expr Expr
          | Fu Fu Expr
          deriving (Eq)

现在第二个OpFu指定了第一个参数的类型。

现在你必须替换你的:

let anExpr = Add (Num 3.0) (Num 4.0)

使用:

let anExpr = Op Add (Num 3.0) (Num 4.0)

基于此,我们可以定义一些帮助函数:

showOp :: Op -> String
showOp Add = "+"
showOp Mul = "*"

showFu :: Fu -> String
showFu Sin = "sin"
showFu Cos = "cos"

现在我们可以在定义showExpr时使用这些辅助函数(我不会称之为printOut,因为函数打印一些东西,它只生成一个string,你可以用那个字符串做任何你想做的事。)

showExpr :: Expr -> String
showExpr (Num n) = show n
showExpr X = "x"
showExpr (Op o a b) = '(' : showExpr a ++ ')' : showOp o ++ '(' : showExpr b ++ ")"
showExpr (Fu f a) = showFu f ++ '(' : showExpr a ++ ")"

例如:

*Main> showExpr (Op Add (Num 3.0) (Num 4.0))
"(3.0)+(4.0)"
*Main> showExpr (Op Add (Num 3.0) (Fu Sin (Num 4.0)))
"(3.0)+(sin(4.0))"

答案 1 :(得分:3)

当你模式匹配时,你需要匹配你传入的构造函数。在你的例子中,Expr可以有一个Operator构造函数,其中包含要打印的相关信息:

printOut (Num n) = show n
printOut X = "x"
printOut (Operator op a b) = printOut a ++ printOp op ++ printOut b
printOut (Function fu a) = printFun fu ++ printOut a

现在,您只需为运算符和函数定义其他模式匹配项:

printOp Add = "+"
printOp Mul = "x"

printFun Sin = "Sin"
printFun Cos = "Cos"

除了@WillemVanOnsem写的内容之外,你实际上并没有用这些" print"来打印任何东西。功能。相反,您将它们从您的数据类型转换为字符串。有一个称为Show的常见类型类。您也可以只为类型创建show实例,并使用该函数来显示它们:

instance Show Fu where 
  show Sin = "Sin"
  show Cos = "Cos" 

然后使用show代替:

printOut (Function fu a) = show fu ++ printOut a

当您拥有show的简单实例时,您也可以使用与导出Eq相同的语法自动导出它:

data Fu = Sin | Cos
        deriving (Show, Eq)

要处理创建Expr的实例,请再次使用各种构造函数来执行此操作:

let anExpr = Operator Add (Num 3.0) (Num 4.0)