Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No instance for (Fractional Int) arising from a use of `/'

Tags:

haskell

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.

like image 428
Nayana Avatar asked Feb 01 '13 23:02

Nayana


People also ask

What is fractional Haskell?

Fractional numbers, supporting real division. The Haskell Report defines no laws for Fractional. However, (+) and (*) are customarily expected to define a division ring and have the following properties: recip gives the multiplicative inverse x * recip x = recip x * x = fromInteger 1.

What does fromIntegral do in Haskell?

The workhorse for converting from integral types is fromIntegral , which will convert from any Integral type into any Num eric type (which includes Int , Integer , Rational , and Double ): fromIntegral :: (Num b, Integral a) => a -> b.


2 Answers

-- 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 Ints. 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:

  1. The context Fractional a
  2. 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 Ints.

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.

like image 105
Ben Avatar answered Sep 22 '22 03:09

Ben


The problem you're having is that Haskell has different functions for integer and 'fractional' division. Integer division truncates, fractional division does not. So instead of

prim Div [Number a, Number b] = Number (a / b) 

you want to do

prim Div [Number a, Number b] = Number (a `div` b) 

What the error message actually means is that the function (/) is part of the Fractional class. This is basically an interface that different types can implement. To get information on it fire up ghci and do

Prelude> :i (/) class Num a => Fractional a where (/) :: a -> a -> a ... -- Defined in `GHC.Real' infixl 7 /  Prelude> :i Int data Int = GHC.Types.I# GHC.Prim.Int#   -- Defined in `GHC.Types' instance Bounded Int -- Defined in `GHC.Enum' instance Enum Int -- Defined in `GHC.Enum' instance Eq Int -- Defined in `GHC.Classes' instance Integral Int -- Defined in `GHC.Real' instance Num Int -- Defined in `GHC.Num' instance Ord Int -- Defined in `GHC.Classes' instance Read Int -- Defined in `GHC.Read' instance Real Int -- Defined in `GHC.Real' instance Show Int -- Defined in `GHC.Show' 

The first gives you information about the function (/): it tells you that it is in the class Fractional. Then when you :i Int it shows you all the instances for Int. Notice that Int is not an instance of Fractional so you can't use (/) with Int.

Another tip: The backticks (`) turn a function into an infix operator so

a `div` b 

is the same as

div a b 
like image 39
Paul Avatar answered Sep 23 '22 03:09

Paul