I'm working on a function that can count the number of operators used in an expression. My code is as follows:
data Expr = Lit Int |
Expr :+: Expr |
Expr :-: Expr
size :: Expr -> Int
size (Lit n) = 0
size (e1 :+: e2) = 1 + (size e1) + (size e2)
size (e1 :-: e2) = 1 + (size e1) + (size e2)
But when I try to execute this code using Hugs98 i get the following error:
Main> size 2+3
ERROR - Cannot infer instance
*** Instance : Num Expr
*** Expression : size 2 + 3
Can somebody tell me what I'm doing wrong? I'm really out of idea's myself.
2+3 is not a valid expression. With your types, primtive values are created using the Lit data constructor, and the valid operators are :+: and :-:. So what you really need is Lit 2 :+: Lit 3. So try
size (Lit 2 :+: Lit 3)
You can make it a Num instance:
instance Num Expr where
(+) = (:+:)
(-) = (:-:)
negate = (0 -)
fromInteger = Lit . fromInteger
(*) = error "not implemented"
abs = error "not implemented"
signum = error "not implemented"
Once that is in place, size (2+3) will work (note the parenthesis).
Related
The If data constructor (If BoolType Expr Expr) should evaluate the Boolean expression (first argument) and return the value of the second argument if it is true or return the third argument. I can construct an evaluation of the expression Expr but I don't understand how to incorporate the nested expression BoolType in order to evaluate an expression. A bit too twisty, I can't get my head around it.
Here's two data types:
data Expr = Val Int
| Add Expr Expr
| Sub Expr Expr
| Mul Expr Expr
| Div Expr Expr
| If BoolType Expr Expr
data BoolType = Lit Bool
| Or BoolType BoolType
| EqualTo Expr Expr
| LessThan Expr Expr
I wrote an expression that evaluates the type:
eval :: BoolType -> Bool
eval (Lit n) = n
eval (Or e1 e2) = eval e1 || eval e2
eval (EqualTo e1 e2) = num e1 == num e2
eval (LessThan e1 e2) = num e1 < num e2
num :: Expr -> Int
num (Val n) = n
num (Add e1 e2) = num e1 + num e2
num (Sub e1 e2) = num e1 - num e2
num (Mul e1 e2) = num e1 * num e2
num (Div e1 e2) = num e1 `div` num e2
It should evaluate out to any normal equation but how do I even incorporate an If boolean data type into the total equation?
The evaluator functions currently have incomplete pattern matches:
*Q55835635> :l 55835635.hs
[1 of 1] Compiling Q55835635 ( 55835635.hs, interpreted )
55835635.hs:22:1: warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In an equation for `num': Patterns not matched: (If _ _ _)
|
22 | num (Val n) = n
| ^^^^^^^^^^^^^^^^^^^^^^^^^...
Ok, one module loaded.
Just add the missing pattern to num:
num :: Expr -> Int
num (Val n) = n
num (Add e1 e2) = num e1 + num e2
num (Sub e1 e2) = num e1 - num e2
num (Mul e1 e2) = num e1 * num e2
num (Div e1 e2) = num e1 `div` num e2
num (If b e1 e2) = if (eval b) then num e1 else num e2
You can now evaluate expressions, including those with If expressions:
*Q55835635> num $ Add (Val 40) (If (Lit True) (Val 2) (Val 0))
42
The rest of the functions aren't necessary.
You can proceed with your approach, adding a suitable equation:
value (If cond e1 e2) = ifHelper (eval cond) (value e1) (value e2)
Then, you need to define your helper:
ifHelper :: Bool -> Maybe Int -> Maybe Int -> Maybe Int
ifHelper True m1 m2 = ...
ifHelper False m1 m2 = ...
By the way, it is usually recommended to define the type of any function before starting to write the function itself. This helps both the programmer (who can reason about what type are the arguments) and the compiler (which can produce better error messages if something goes wrong).
Turning on warnings with the -Wall flag is also a good idea, since warnings can spot several potential errors.
I'm wrote a unique data type to express basic math (addition, mult, etc.) and it works - however, when I try to turn it into a Maybe statement, none of the math works. I believe it's a syntax error but I've tried extra parenthesis and so on and I can't figure it out. Usually Maybe statements are easy but I don't understand why it keeps throwing an issue.
This is the data type I created (with examples):
data Math = Val Int
| Add Math Math
| Sub Math Math
| Mult Math Math
| Div Math Math
deriving Show
ex1 :: Math
ex1 = Add1 (Val1 2) (Val1 3)
ex2 :: Math
ex2 = Mult (Val 2) (Val 3)
ex3 :: Math
ex3 = Div (Val 3) (Val 0)
Here is the code. The only Nothing return should be a division by zero.
expression :: Math -> Maybe Int
expression (Val n) = Just n
expression (Add e1 e2) = Just (expression e1) + (expression e2)
expression (Sub e1 e2) = Just (expression e1) - (expression e2)
expression (Mult e1 e2) = Just (expression e1) * (expression e2)
expression (Div e1 e2)
| e2 /= 0 = Just (expression e1) `div` (expression e2)
| otherwise = Nothing
I get the same error for every individual mathematical equation, even if I delete the others, so I'm certain it's syntax. The error makes it seem like a Maybe within a Maybe but when I do that e1 /= 0 && e2 /= 0 = Just (Just (expression e1)div(expression e2)), I get the same error:
* Couldn't match type `Int' with `Maybe Int'
Expected type: Maybe (Maybe Int)
Actual type: Maybe Int
* In the second argument of `div', namely `(expression e2)'
In the expression: Just (expression e1) `div` (expression e2)
In an equation for `expression':
expression (Div e1 e2)
| e1 /= 0 && e2 /= 0 = Just (expression e1) `div` (expression e2)
| otherwise = Nothing
|
56 | | e1 /= 0 && e2 /= 0 = Just (expression e1) `div` (expression e2)
| ^^^^^^^^^
What am I missing? It's driving me crazy.
So the first issue is precedence. Instead of writing:
Just (expression e1) * (expression e2)
You probably want:
Just (expression e1 * expression e2)
The second issue is the types. Take a look at the type of (*), for instance:
>>> :t (*)
(*) :: Num a => a -> a -> a
It says, for some type a that is a Num, it takes two as and returns one a. Specialised to Int, that would be:
(*) :: Int -> Int -> Int
But expression returns a Maybe Int! So we need some way to multiply with Maybes. Let's write the function ourselves:
multMaybes :: Maybe Int -> Maybe Int -> Maybe Int
multMaybes Nothing _ = Nothing
multMaybes _ Nothing = Nothing
multMaybes (Just x) (Just y) = Just (x * y)
So if either side of the multiplication has failed (i.e. you found a divide-by-zero), the whole thing will fail. Now, we need to do this once for every operator:
addMaybes Nothing _ = Nothing
addMaybes _ Nothing = Nothing
addMaybes (Just x) (Just y) = Just (x + y)
subMaybes Nothing _ = Nothing
subMaybes _ Nothing = Nothing
subMaybes (Just x) (Just y) = Just (x - y)
And so on. But we can see there's a lot of repetition here. Luckily, there's a function that does this pattern already: liftA2.
multMaybes = liftA2 (*)
addMaybes = liftA2 (+)
subMaybes = liftA2 (-)
Finally, there are two more small problems. First, you say:
expression (Div e1 e2)
| e2 /= 0 = Just (expression e1) `div` (expression e2)
But e2 isn't an Int! It's the expression type. You probably want to check if the result of the recursive call is 0.
The second problem is that you're unnecessarily wrapping things in Just: we can remove one layer.
After all of that, we can write your function like this:
expression :: Math -> Maybe Int
expression (Val n) = Just n
expression (Add e1 e2) = liftA2 (+) (expression e1) (expression e2)
expression (Sub e1 e2) = liftA2 (-) (expression e1) (expression e2)
expression (Mult e1 e2) = liftA2 (*) (expression e1) (expression e2)
expression (Div e1 e2)
| r2 /= Just 0 = liftA2 div (expression e1) r2
| otherwise = Nothing
where r2 = expression e2
There are two problems here:
Just (expression e1) + (expression e2)
is interpreted as:
(Just (expression e1)) + (expression e2)
So that means that you have wrapped the left value in a Just, whereas the other one is not, and this will not make much sense.
Secondly, both expression e1 and expression e2 have type Maybe Int, hence that means that you can not add these two together. We can perform pattern matching.
Fortunately there is a more elegant solution: we can make use of liftM2 :: Monad m => (a -> b -> c) -> m a -> m b -> m c for most of the patterns. For Maybe the liftM2 will take a function f :: a -> b -> c and two Maybes, and if both are Justs it will call the function on the values that are wrapped in the Justs and then wrap the result in a Just as well.
As for the division case, we will first have to obtain the result of the denominator with the expression function, and if that is a Just that is not equal to zero, then we can fmap :: Functor f => (a -> b) -> f a -> f b function to map a value in a Just (that of the numerator) given of course the numerator is a Just:
import Control.Monad(liftM2)
expression :: Math -> Maybe Int
expression (Val n) = Just n
expression (Add e1 e2) = liftM2 (+) (expression e1) (expression e2)
expression (Sub e1 e2) = liftM2 (-) (expression e1) (expression e2)
expression (Mult e1 e2) = liftM2 (*) (expression e1) (expression e2)
expression (Div e1 e2) | Just v2 <- expression e2, v2 /= 0 = fmap (`div` v2) (expression e1)
| otherwise = Nothing
or we can, like #RobinZigmond says, use (<$>) :: Functor f => (a -> b) -> f a -> f b and (<*>) :: Applicative f => f (a -> b) -> f a -> f b:
expression :: Math -> Maybe Int
expression (Val n) = Just n
expression (Add e1 e2) = (+) <$> expression e1 <*> expression e2
expression (Sub e1 e2) = (-) <$> expression e1 <*> expression e2
expression (Mult e1 e2) = (*) <$> expression e1 <*> expression e2
expression (Div e1 e2) | Just v2 <- expression e2, v2 /= 0 = (`div` v2) <$> expression e1
| otherwise = Nothing
i am making tiny language. Let E be a tiny programming language that supports the declaration of arithmetic expressions and equality comparison on integers.
given the following data type E:
data E = IntLit Int
| BoolLit Bool
| Plus E E
| Minus E E
| Multiplies E E
| Exponentiate E E
| Equals E E
deriving (Eq, Show)
here is my code with above data it is working all of these.
data E = IntLit Int
| BoolLit Bool
| Plus E E
| Minus E E
| Multiplies E E
| Divides E E
| Equals E E
| log2Sim E E
deriving (Eq, Show)
eval :: E -> E
eval c#(IntLit i) = c
eval c#(BoolLit b) = c
eval (Plus a b) = plus (eval a) (eval b)
eval (Minus a b) = minus (eval a) (eval b)
eval (Multiplies a b) = multiplies (eval a) (eval b)
eval (Divides a b) = divides (eval a) (eval b)
eval (Equals a b) = equals (eval a) (eval b)
log2Sim :: E -> E
log2sim = case (eval x) of
IntLit i -> IntLit (logBase 2 i)
x1 -> "type error: can't take the log of a non-IntLit-valued expresstio" ++ show x1
plus (IntLit i) (IntLit j) = IntLit $ i + j
plus _ _ = error "Type error in addition"
minus (IntLit i) (IntLit j) = IntLit $ i - j
minus _ _ = error "Type error in subtraction"
multiplies (IntLit i) (IntLit j) = IntLit $ i * j
multiplies _ _ = error "Type error in multiplication"
divides (IntLit i) (IntLit j) = IntLit $ i `div` j
divides _ _ = error "Type error in division"
equals (IntLit i) (IntLit j) = BoolLit $ i == j
equals (BoolLit a) (BoolLit b) = BoolLit $ a == b
equals _ _ = error "Type error in equals"
when i compiled it, there are some errors.
what error is this?
A3.hs:56:7:
Couldn't match expected type `E' against inferred type `[Char]'
In the expression:
"type error: can't take the lof of a non-IntLit-valued expression: "
++
show x1
In a case alternative:
x1
-> "type error: can't take the lof of a non-IntLit-valued expression: "
++
show x1
In the expression:
case (eval x) of
IntLit i -> IntLit (logBase 2 i)
x1
-> "type error: can't take the lof of a non-IntLit-valued expression: "
++
show x1
There are many problems in your code:
All constructors must start with an upper-case letter. So data E = ... | log2Sim E E is incorrect. You also probably just want one E, hence for example data E = ... | Log E would fix both these problems.
You declared log2Sim but defined log2sim (notice the difference in capitalization). You also forgot to write the argument x to the left of the = in the definition. Fix both problems by writing
log2Sim x = ...
Strings are not valid expressions of type E. You probably wanted to follow the pattern in the rest of your code by calling error to turn your error string into an E. Thus:
x1 -> error $ "type error: can't take the log of a non-IntLit-valued expresstio" ++ show x1
logBase operates on Floating-point numbers, and Int is not one. There's a few ways to fix this, but the shortest distance between here and there is to convert to a Double and back. For example:
IntLit i -> IntLit . floor . logBase 2 . fromIntegral $ i
This is enough to make your code compile, though there may be other problems.
When doing calculations modulo n with large numbers, you will encounter huge performency penalties when doing for example mod (123456789^987654321) n. Instead you have to use your own ^ that internally calculates mod n also for intermedite calculations.
Sure, I can easily implement my own functions, but then I have to explicitly say "mod n" for each operation. Instead one could build an numeric expression tree and defer actual calculations, and in the end state modulo n only once. (see my code below)
I started on this to clearly show what I mean, but I wonder if there already exists implementations of this, it seems quite useful so somebody ought to have implemented it.
module Modulo where
data Expr =
V Integer
| Plus Expr Expr
| Mult Expr Expr
deriving (Eq, Show)
instance Num Expr where
(+) = Plus
(*) = Mult
fromInteger = V
eval :: Integer -> Expr -> Integer
eval m (V i) = i `mod` m
eval m (Plus e1 e2) = (eval m e1 + eval m e2) `mod` m
eval m (Mult e1 e2) = (eval m e1 * eval m e2) `mod` m
fifteen :: Expr
fifteen = 10 + 5
test = eval 13 fifteen
Oleg did something of this kind, where you make an instance for modulo arithmetic, but for a arbitrary modulus. Implicit configurations.
Exercise 14.16-17 in Thompson asks me to add the operations of multiplication and (integer) division to the type Expr, which represents a simple language for arithmetic, then define the functions show and eval (evaluates an expression of type Expr) for Expr.
My solution works for each arithmetic operation except division:
data Expr = L Int
| Expr :+ Expr
| Expr :- Expr
| Expr :* Expr
| Expr :/ Expr
instance Num Expr where
(L x) + (L y) = L (x + y)
(L x) - (L y) = L (x - y)
(L x) * (L y) = L (x * y)
instance Eq Expr where
(L x) == (L y) = x == y
instance Show Expr where
show (L n) = show n
show (e1 :+ e2) = "(" ++ show e1 ++ " + " ++ show e2 ++ ")"
show (e1 :- e2) = "(" ++ show e1 ++ " - " ++ show e2 ++ ")"
show (e1 :* e2) = "(" ++ show e1 ++ " * " ++ show e2 ++ ")"
show (e1 :/ e2) = "(" ++ show e1 ++ " / " ++ show e2 ++ ")"
eval :: Expr -> Expr
eval (L n) = L n
eval (e1 :+ e2) = eval e1 + eval e2
eval (e1 :- e2) = eval e1 - eval e2
eval (e1 :* e2) = eval e1 * eval e2
E.g.,
*Main> (L 6 :+ L 7) :- L 4
((6 + 7) - 4)
*Main> it :* L 9
(((6 + 7) - 4) * 9)
*Main> eval it
81
it :: Expr
However, I am running into problems when I try to implement division. I don't understand the error message I receive when I try to compile the following:
instance Integral Expr where
(L x) `div` (L y) = L (x `div` y)
eval (e1 :/ e2) = eval e1 `div` eval e2
This is the error:
Chapter 14.15-27.hs:19:9:
No instances for (Enum Expr, Real Expr)
arising from the superclasses of an instance declaration
at Chapter 14.15-27.hs:19:9-21
Possible fix:
add an instance declaration for (Enum Expr, Real Expr)
In the instance declaration for `Integral Expr'
In the first place, I have no idea why defining div for the data type Expr requires me to define an instance of Enum Expr or Real Expr.
Well, that's the way the Integral typeclass is defined. For information, you can e.g. just type :i Integral into GHCi.
You'll get
class (Real a, Enum a) => Integral a where ...
which means any type a that should be Integral has to be Real and Enum first. C'est la vie.
Note that maybe you've got your types messed up quite a bit. Take a look at
instance Num Expr where
(L x) + (L y) = L (x + y)
(L x) - (L y) = L (x - y)
(L x) * (L y) = L (x * y)
This just allows you to add Expressions if they wrap plain numbers. I'm pretty sure you don't want that.
You want to add arbitrary expressions and you already have a syntax for this. It's just
instance Num Expr where
(+) = (:+)
(-) = (:-)
-- ...
This allows you to write (L 1) + (L 2) with perfectly normal syntax. Likewise, eval should not just reduce expressions but yield a number, and therefore have the type eval :: Expr -> Integer. Division is simple for that matter
eval (a :/ b) = (eval a) `div` (eval b)
which is defined since you just divide numbers.