如果我有三种名为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
我该怎么做?
答案 0 :(得分:5)
您无法将对类型的引用写为构造函数名称。在您的代码中:
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"
现在我们可以在定义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)