I am new to Haskell, and I am struggling with debugging my code.
Fixing an error leads to other errors…
Here is my code.
import Data.Maybe
data Op = Add | Sub | Mul | Div | And | Or | Not | Eq | Less | Great
deriving (Eq, Show)
data Exp = Literal Value
| Primitive Op [Exp]
| Variable String
| If Exp Exp Exp
| Let [(String, Exp)] Exp
deriving (Show, Eq)
data Value = Number Int
| Bool Bool
| String String
deriving (Eq, Show)
type Env = [(String, Value)]
eval :: Env -> Exp -> Value
eval e (Literal v) = v
eval e (Variable x) = fromJust (lookup x e) --22
prim :: Op -> [Value] -> Value
prim Add [Number a, Number b] = Number (a + b)
prim And [Bool a, Bool b] = Bool (a && b)
prim Sub [Number a, Nuamber b] = Number (a - b) -- No instance for (Fractional Int) arising from a use of `/'
prim Mul [Number a, Number b] = Number (a * b)
prim Div [Number a, Number b] = Number (a / b)
prim Or [Bool a, Bool b] = Bool (a || b)
prim Not [Bool a] = Bool (not a)
prim Eq [Number a, Number b] = Bool (a == b)
prim Eq [String a, String b] = Bool (a == b)
prim Less [Number a, Number b] = Bool (a < b)
prim Less [String a, String b] = Bool (a < b)
prim Great [Number a, Number b] = Bool (a > b)
prim Great [String a, String b] = Bool (a > b) --37
main = do
eval [("y", (Number 40))] (Let [("x", (Literal (Number 2)))] (prim Add [(Variable "x"), (Variable "y")])) -- Couldn't match expected type `Exp' with actual type `Value'
I am now getting two errors which I wrote in comments.
If you know what’s wrong with my code, please share your idea and save my time…
Thank you very much.
Presumably that’s coming from this line rather than the one with your comment:
aandbareInts. The division operator is(/) :: Fractional a => a -> a -> a(you can find that out by firing up ghci and entering:t (/), or by looking it up on Hoogle).If you haven’t seen types like
Fractional a => a -> a -> a, you should read this in two parts:Fractional aa -> a -> aThis is just like a regular
a -> a -> atype, so it takes two arguments of some type and gives you back a result of the same type. The only difference in adding theFractional acontext is that type used foramust be an instance of theFractionaltype class; it isn’t free to range over any type you like.If you haven’t learned about type classes yet don’t worry. They’re pretty easy to grasp, but not something you should be looking at in depth when you’re just starting; you’ll get to them later.
Intisn’t a member of theFractionaltype class, so the/operator doesn’t work onInts.The reason is that regular mathematical division doesn’t work on integers with this type;
3 / 2would have to either give1.5, in which case it doesn’t fit the typeInt -> Int -> Int, or give1or2, in which case it wouldn’t be correct mathematical division. There is a functiondivfor implementing integer division, usable likea `div` bin infix notation.This message is about your own types, in a single expression you wrote. And the actual full error message would have given you more context about which part of the expression contains the error. Just follow it through from the top down, checking the types of things yourself and the error very quickly leaps out at you.
In this case, you get to here:
Letneeds two arguments, a[(String, Exp)]and anExp. The list is fine, but the second argument is(prim Add [(Variable "x"), (Variable "y")]). Without even digging into the substructure of that to see if it’s correct,primhas typeOp -> [Value] -> Value, so there’s no way it’s going to give you anExp.How to fix that is up to you; it looks like you need a bit of a refactor across the whole expression/value distinction.
primgives you anValue, which you could simply apply wrap in aLiteralto get you past the type error you’re getting, but then you run into the problem thatprimshould be taking anOpand a[Value], but you appear to have given it anOpand a[Exp](containing variables). I think you need to think about the difference between usingprimto compute the results of a primitive application, using thePrimitiveconstructor ofExpto represent a primitive application, and usingevalto evaluate (in an environment) an arbitrary expression (which may contain several primitive applications) to a value.