Harry
Harry

Reputation: 11638

Haskell types error: Inferred type is less polymorphic than expected

I'm messing around with Haskell at the moment and for the life of me I cannot figure out why the following works.....

square :: (Num a) => a -> a 
square x = x * x 
dx = 0.0000001
deriv1 :: (Fractional a) => (a -> a) -> (a -> a)
deriv1 g = (\x -> ((g (x + 2) - (g x)) / 0.0000001 ))   
main = printf "res==%g %g\n" (square 5.12::Double) ((deriv1 square) 2::Float)

but this doesn't....

square :: (Num a) => a -> a 
square x = x * x 
dx = 0.0000001
deriv1 :: (Fractional a) => (a -> a) -> (a -> a)
deriv1 g = (\x -> ((g (x + 2) - (g x)) / dx ))          
main = printf "res==%g %g\n" (square 5.12::Double) ((deriv1 square) 2::Float)

note I've used dx in the derv1 function this time. I'm new to Haskell so any in depth discussion on types will likely whoosh past me so fast I'll die spinning. It's imperative I have something resembling an imperative answer or it will almost certainly be lost on me this early in my Haskell career.

The error message I'm getting is:

Inferred type is less polymorphic than expected
  Quantified type variable `a' is mentioned in the environment:
    dx :: a (bound at sicp-1.40.hs:12:0)
When trying to generalise the type inferred for `deriv1'
  Signature type:     forall a. (Fractional a) => (a -> a) -> a -> a
  Type to generalise: (a -> a) -> a -> a
In the type signature for `deriv1'
When generalising the type(s) for `deriv1'

Upvotes: 3

Views: 170

Answers (3)

leftaroundabout
leftaroundabout

Reputation: 120711

The probably best way to avoid ending up in the monomorphism restriction is to make dx local:

deriv1 :: (Fractional a) => (a->a) -> a->a
deriv1 g = (\x -> ((g (x + dx) - (g x)) / dx ))
   where dx = 0.0000001

Note that I changed 2 for dx as well, that was kind of wrong in your definition. (Not programming-wise, but mathematically.)

BTW, you can also write this simply

deriv1 g x = (g (x + dx) - g x) / dx

Haskell translates it to a lambda automatically.

Upvotes: 4

sepp2k
sepp2k

Reputation: 370082

Due to the monomorphism restriction, the type of dx is defaulted to Double. So when you divide by dx in deriv1, Haskell infers that the other operand to / and the result must also have type Double. But since your type signature says a, you get the error you do.

You can fix this by either explicitly declaring dx to have the type Fractional a => a or by disabling the monomorphism restriction.

Upvotes: 2

shang
shang

Reputation: 24802

You get the error because of the monomorphism restriction. Since you don't give a type signature to dx it ends up inferred as Double in this case. You can either give an explicit, polymorphic signature like

dx :: Fractional a => a
dx = 0.0000001

or you can disable the monomorphism restriction by including this line at the top of your source file

{-# LANGUAGE NoMonomorphismRestriction #-}

Upvotes: 6

Related Questions