简体   繁体   中英

Typed Racket Polymorphic Function cannot be applied

> (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.

The problem is one of the following:

  1. you are declaring the parameter x to be a Number
  2. You are declaring sum to work with Real 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).

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 ...))

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM