What to do with “Inferred type is less polymorphic than expected”?
Question
I need the Numeric.FAD library, albeit still being completely puzzled by existential types.
This is the code:
error_diffs :: [Double] -> NetworkState [(Int, Int, Double)]
error_diffs desired_outputs = do diff_error <- (diff_op $ error' $ map FAD.lift desired_outputs)::(NetworkState ([FAD.Dual tag Double] -> FAD.Dual tag Double))
weights <- link_weights
let diffs = FAD.grad (diff_error::([FAD.Dual tag a] -> FAD.Dual tag b)) weights
links <- link_list
return $ zipWith (\link diff ->
(linkFrom link, linkTo link, diff)
) links diffs
error' runs in a Reader monad, ran by diff_op, which in turn generates an anonymous function to take the current NetworkState and the differential inputs from FAD.grad and stuffs them into the Reader.
Haskell confuses me with the following:
Inferred type is less polymorphic than expected
Quantified type variable `tag' is mentioned in the environment:
diff_error :: [FAD.Dual tag Double] -> FAD.Dual tag Double
(bound at Operations.hs:100:33)
In the first argument of `FAD.grad', namely
`(diff_error :: [FAD.Dual tag a] -> FAD.Dual tag b)'
In the expression:
FAD.grad (diff_error :: [FAD.Dual tag a] -> FAD.Dual tag b) weights
In the definition of `diffs':
diffs = FAD.grad
(diff_error :: [FAD.Dual tag a] -> FAD.Dual tag b) weights
Solution
If I write,
bigNumber :: (Num a) => a
bigNumber = product [1..100]
then when bigNumber :: Int
is evaluated,
it's evaluating (product :: [Int] -> Int) [(1 :: Int) .. (100 :: Int)]
,
and when bigNumber :: Integer
is evaluated,
it's evaluating (product :: [Integer] -> Integer) [(1 :: Integer) .. (100 :: Integer)]
.
Nothing is shared between the two.
error_diffs
has a single type, that is: [Double] -> NetworkState [(Int, Int, Double)]
. It must evaluate in exactly one way.
However, what you have inside:
... :: NetworkState ([FAD.Dual tag Double] -> FAD.Dual tag Double)
can be evaluated in different ways, depending on what tag
is.
See the problem?
OTHER TIPS
this code gives the same error as you get:
test :: Int
test =
(res :: Num a => a)
where
res = 5
The compiler figured that res
is always of type Int
and is bothered that for some reason you think res
is polymorphic.
this code, however, works fine:
test :: Int
test =
res
where
res :: Num a => a
res = 5
here too, res
is defined as polymorphic but only ever used as Int
. the compiler is only bothered when you type nested expressions this way. in this case res
could be reused and maybe one of those uses will not use it as Int
, in contrast to when you type a nested expression, which cannot be reused by itself.