If I have three data types named Expr
, Op
and Fu
like this.
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)
What I am supposed to do is later create an expression based on the datatype. For example
let anExpr = Add (Num 3.0) (Num 4.0)
And than print out the corresponding expression, in this case it should just be "3.0+4.0".
The problem I am facing is to create another type or data type to recognize if it is an addition or multiplication symbol it is supposed to print out. What I would like to do is something like this in pseudo code
printOut (Num n) = show n
printOut X = "x"
printOut (Op a b) = printOut a ++ 'printOutRightOp' ++ printOut b
printOut (Fu a) = 'printOutRightFu' ++ printOut a
How am I supposed to do this?
There are two ways for changing any data type into a String in Python : Using the str() function. Using the __str__() function.
To convert an integer to string in Python, use the str() function. This function takes any data type and converts it into a string, including integers. Use the syntax print(str(INT)) to return the int as a str , or string.
You can not write references to types as constructor name. In your code:
data Expr = Num Double
| X
| Op Expr Expr
| Fu Expr
deriving (Eq)
Op
and Fu
are the names of the constructors. Haskell considers the fact that there is a type with the same name, just a coincidence. You have to add the type of operator/function as first argument. So:
data Expr = Num Double
| X
| Op Op Expr Expr
| Fu Fu Expr
deriving (Eq)
Now the second Op
and Fu
specify the types of the first parameters.
Now you thus have to replace your:
let anExpr = Add (Num 3.0) (Num 4.0)
with:
let anExpr = Op Add (Num 3.0) (Num 4.0)
Based on that, we can define some helper functions:
showOp :: Op -> String
showOp Add = "+"
showOp Mul = "*"
showFu :: Fu -> String
showFu Sin = "sin"
showFu Cos = "cos"
Now we can use these helper functions when we define our showExpr
(I would not call it printOut
, since the function does not print something, it only generates a string, you can do whatever you want with that 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 ++ ")"
For example:
*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))"
When you pattern match, you need to match on the constructor you passed in. In your example, an Expr
can have an Operator
constructor that contains the relevant information to print:
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
Now you just define additional pattern matches for your operators and functions:
printOp Add = "+"
printOp Mul = "x"
printFun Sin = "Sin"
printFun Cos = "Cos"
In addition to what @WillemVanOnsem wrote, you actually aren't printing anything to the screen with these "print" functions. Instead, you are converting them from your datatype to a string. There is a common typeclass that does that called Show
. You could also just create instances of show for your types, and use that function to display them instead:
instance Show Fu where
show Sin = "Sin"
show Cos = "Cos"
and then use show
instead:
printOut (Function fu a) = show fu ++ printOut a
When you have a simple instance of show
, you can also just have it derived automatically for you using the same syntax as you are using for deriving Eq
:
data Fu = Sin | Cos
deriving (Show, Eq)
To deal with creating an instance of Expr
, again you use the various constructors to do so:
let anExpr = Operator Add (Num 3.0) (Num 4.0)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With