Reputation: 11638
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
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
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
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