-- No instance for (Fractional Int) arising from a use of `/'
Presumably that's coming from this line rather than the one with your comment:
prim Div [Number a, Number b] = Number (a / b)
a
and b
are Int
s. 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:
- The context
Fractional a
- The type
a -> a -> a
This is just like a regular a -> a -> a
type, so it takes two arguments of some type and gives you back a result of the same type. The only difference in adding the Fractional a
context is that type used for a
must be an instance of the Fractional
type 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.
Int
isn't a member of the Fractional
type class, so the /
operator doesn't work on Int
s.
The reason is that regular mathematical division doesn't work on integers with this type; 3 / 2
would have to either give 1.5
, in which case it doesn't fit the type Int -> Int -> Int
, or give 1
or 2
, in which case it wouldn't be correct mathematical division. There is a function div
for implementing integer division, usable like a `div` b
in infix notation.
-- Couldn't match expected type `Exp' with actual type `Value'
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:
Let [("x", (Literal (Number 2)))] (prim Add [(Variable "x"), (Variable "y")])
Let
needs two arguments, a [(String, Exp)]
and an Exp
. 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, prim
has type Op -> [Value] -> Value
, so there's no way it's going to give you an Exp
.
How to fix that is up to you; it looks like you need a bit of a refactor across the whole expression/value distinction. prim
gives you an Value
, which you could simply apply wrap in a Literal
to get you past the type error you're getting, but then you run into the problem that prim
should be taking an Op
and a [Value]
, but you appear to have given it an Op
and a [Exp]
(containing variables). I think you need to think about the difference between using prim
to compute the results of a primitive application, using the Primitive
constructor of Exp
to represent a primitive application, and using eval
to evaluate (in an environment) an arbitrary expression (which may contain several primitive applications) to a value.