将自定义数据类型转换为字符串
问题描述:
如果我有三种数据类型,分别为Expr
,Op
和Fu
。将自定义数据类型转换为字符串
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
我该如何做到这一点? 。
答
您不能写入类型的引用作为构造名。在您的代码:
data Expr = Num Double
| X
| Op Expr Expr
| Fu Expr
deriving (Eq)
Op
和Fu
是构造的名。 Haskell认为这是一个同名的类型,这只是一个巧合。您必须添加操作符/函数的类型作为第一个参数。所以:
data Expr = Num Double
| X
| Op Op Expr Expr
| Fu Fu Expr
deriving (Eq)
现在第二Op
和Fu
指定类型的第一个参数。
现在,所以你必须更换:
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"
现在我们当我们定义我们的时可以使用这些帮助函数(我不会叫它printOut
,因为功能确实不是而是打印的东西,它只会产生一个字符串,你可以对该字符串做任何你想做的事情)。
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))"
答
当你的模式匹配,你需要匹配你传递的构造在您的例子,一个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写的,你居然不打印任何东西到屏幕上与这些“打印”功能。相反,你正在将它们从你的数据类型转换成一个字符串。有一种常见的类型类别叫做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)
但是'Op'和'Fu'在'Expr'是建设者的** **的名字。 –
对不起,修正了这个问题 – Salviati
@Salviati你刚开始有一个拼写错误,应该是“如果我有三种数据类型** Expr **,Op和Fu”...... – jkeuhlen