I want to make a list of numbers every 0.1
from -150
to 150
.
To do this, I created a list, and then tried to map a Fractional multiplication lambda onto it, like so:
let indices = [-1500,-1499..1500]
let grid = map (\x -> 0.1 *x) indices
This makes ghci spit out an error.
On the other hand, both of these work fine:
let a = 0.1*2
and
let grid = map (\x -> 2 *x) indices
What's going on here? Why does multiplication of a Num by a Fractional only fail when applied to a list with map?
EDIT: The error I get is:
No instance for (Fractional Integer)
arising from the literal `0.1'
Possible fix: add an instance declaration for (Fractional Integer)
In the first argument of `(*)', namely `0.1'
In the expression: 0.1 * x
In the first argument of `map', namely `(\ x -> 0.1 * x)'
You've discovered the "dreaded monomorphism restriction". Basically GHC will infer the type of indices
to be a monotype like [Integer]
instead of Num a => a
. You can either provide an annotation like indices :: [Float]
, or rework your definitions to avoid the restriction.
For example (not a suggestion), if you make indices
a function: let indices a = [-1500, -1499..1500]
, the inferred type is now (Enum t, Num t) => a -> [t]
. The a
parameter is unused but defeats the restriction. Then you can then do map f (indices whatever)
. See much more information in the Haskell Wiki about the Monomorphism Restriction.
This is defaulting.
Your indices
variable, rather than being polymorphic over the Num
typeclass as you might expect, is defaulting to Integer, at which point you can't multiply it by 0.1
, since 0.1
will resolve to some Fractional type.
You could force indices to be polymorphic with an explicit type signature:
let indices :: (Enum a, Num a) => [a]; indices = [-1500,-1499..1500]
although in practice you don't often want explicitly polymorphic lists in that way.
There is a page about the monomorphism restriction on the haskell wiki although it's not particularly succinct : http://www.haskell.org/haskellwiki/Monomorphism_restriction
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With