Looks like the problem is that sum
expects (Listof Real)
but map
was returning (Listof Number)
. The solution is to use (apply + (map ...))
instead of (sum (map ...))
Typed Racket Polymorphic Function cannot be applied
-
13-06-2023 - |
Pergunta
> (map (λ: ([x : (Pairof Symbol Number)]) (cdr x)) (list (cons (quote a) 0.3) (cons (quote b) 0.2) (cons (quote c) 0.5)))
- : (Listof Number) [generalized from (Pairof Number (Listof Number))]
'(0.3 0.2 0.5)
> (sum '(0.3 0.2 0.5))
- : Real
1.0
> (sum (map (λ: ([x : (Pairof Symbol Number)]) (cdr x)) (list (cons (quote a) 0.3) (cons (quote b) 0.2) (cons (quote c) 0.5))))
. Type Checker: Polymorphic function map could not be applied to arguments:
Types: (a -> c) (Pairof a (Listof a)) -> (Pairof c (Listof c))
(a b ... b -> c) (Listof a) (Listof b) ... b -> (Listof c)
Arguments: ((Pairof Symbol Number) -> Number : ((! False @ (cdr) 0) | (False @ (cdr) 0)) (cdr 0)) (List (Pairof 'a Positive-Flonum) (Pairof 'b Positive-Flonum) (Pairof 'c Positive-Flonum))
Expected result: (Listof Real)
in: (map (λ: ((x : (Pairof Symbol Number))) (cdr x)) (list (cons (quote a) 0.3) (cons (quote b) 0.2) (cons (quote c) 0.5)))
Why do the first and second expressions, > (map ...
and > sum ...
work as I expect, but trying to combine them throws a type error?
> sum
- : ((Listof Real) -> Real)
#<procedure:sum>
I don't quite understand why map
is returning a (Listof Number) [generalized from (Pairof Number (Listof Number))]
instead just (Listof Number)
, based on what I thought map
does.
Solução 2
Outras dicas
The problem is one of the following:
- you are declaring the parameter
x
to be aNumber
- You are declaring
sum
to work withReal
s
Somewhere in the (Typed) Racket docs the type tree is explained. The problem with your code is that Real
is a subtype of Number
. So while your map
produces a list of Number
s the sum function will only accept a more specific type which (thankfully) produces an error.
You can fix it by either letting sum handle any kind of Numbers
(assuming you're using + that should be safe to do) or you specifically declare x
to be a Real
(which might not always be correct, but in this limited example works fine).