I'm trying to define product
with foldr
:
I could do it with:
new_product xs = foldr (*) 1 xs
but not:
new_product = foldr (*) 1
or:
new_product = \\xs -> foldr (*) 1 xs
Both definition produce the same error:
No instance for (Foldable t0) arising from a use of 'folder'
The type variable 't0' is ambiguous
Relevant bindings include
new_product :: t0 Integer -> Integer
Is it some kind of type error?
How could I fix it?
This is the Monomorphism restriction at work. The solution is to add a type signature:
new_product :: (Foldable t, Num b) => t b -> b
new_product = foldr (*) 1
Essentially, the problem here is that unless you are in GHCi (where this is disabled) Haskell refuses to infer a polymorphic type signature unless you explicitly have variables for the function. As a concrete example:
f x = ... -- `f` can infer polymorphic type (in `x`)
f = \x -> ... -- `f` infers a monomorphic type
In your case, f
is new_product
and x
is xs
. When you have the point-free style, Haskell attempts to infer a monomorphic signature for new_product
and fails because it can't figure out which Foldable
instance to choose (based on foldr
). On the other hand, when you include the xs
, Haskell is no longer bound to infer a monomorphic signature, hence everything works.
There is reason to this madness: the point is that when you write something like f = ...
it is natural to assume that f
only gets evaluated once. Yet, unless we force f
to be monomorphic, that isn't necessarily the case.
To use an example related to your function: suppose that I infer that p = num_product [1..1000]
has type Num a => a
(the most general type in this case), then using p :: Int
and p :: Integer
will cause us to evaluate p
at least twice.
Haskell has therefore decided not to generalize top-level bindings: you only infer polymorphic signatures for functions that have their variables explicit (ie. on the left hand side of the equal). That said, if you wish to explicitly write a polymorphic type signature, you are free to do so.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.