如果我有三个数据类型命名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)
Run Code Online (Sandbox Code Playgroud)
我应该做的是稍后根据数据类型创建一个表达式.例如
let anExpr = Add (Num 3.0) (Num 4.0)
Run Code Online (Sandbox Code Playgroud)
而且打印出相应的表达式,在这种情况下它应该只是"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
Run Code Online (Sandbox Code Playgroud)
我该怎么做?
您不能将对类型的引用写为构造函数名称.在你的代码中:
data Expr = Num Double
| X
| Op Expr Expr
| Fu Expr
deriving (Eq)
Run Code Online (Sandbox Code Playgroud)
Op
并且Fu
是构造函数的名称.Haskell认为存在一个具有相同名称的类型,只是巧合.您必须添加运算符/函数的类型作为第一个参数.所以:
data Expr = Num Double
| X
| Op Op Expr Expr
| Fu Fu Expr
deriving (Eq)
Run Code Online (Sandbox Code Playgroud)
现在是第二个Op
并Fu
指定第一个参数的类型.
现在你必须更换你的:
let anExpr = Add (Num 3.0) (Num 4.0)
Run Code Online (Sandbox Code Playgroud)
有:
let anExpr = Op Add (Num 3.0) (Num 4.0)
Run Code Online (Sandbox Code Playgroud)
基于此,我们可以定义一些辅助函数:
showOp :: Op -> String
showOp Add = "+"
showOp Mul = "*"
showFu :: Fu -> String
showFu Sin = "sin"
showFu Cos = "cos"
Run Code Online (Sandbox Code Playgroud)
现在,当我们定义我们可以利用这些辅助函数我们showExpr
(我不会把它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 ++ ")"
Run Code Online (Sandbox Code Playgroud)
例如:
*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))"
Run Code Online (Sandbox Code Playgroud)