lisprackettyped-racket

Is it possible to make Typed Racket infer types through mapping functions and lambdas?


In my answer to this question I discovered that you seem to often need to add type annotations to the arguments to anonymous functions used as arguments to mapping functions: map, foldl and so on.

Here are two simple examples (all of these assume #lang typed/racket, and I'm using Racket 8.0).

I'd like this to work:

(define (f (l : (Listof Number)))
  : (Listof Number)
  (map (λ (x)
         (+ x 1))
       l))

But it doesn't: you need to teach it that the argument to x is a Number:

(define (f (l : (Listof Number)))
  : (Listof Number)
  (map (λ ((x : Number))
         (+ x 1))
       l))

or you could use for/list and now you don't need the annotation:

(define (f (l : (Listof Number)))
  : (Listof Number)
  (for/list ([x (in-list l)])
    (+ x 1)))

This on the other hand will work:

(define (g (l : (Listof Number)))
  : Number
  (foldl + 0 l))

But if I replace it with the (slightly silly, but I wanted a tiny example)

(define (g (l : (Listof Number)))
  : Number
  (foldl (λ (x y) (+ x y))  0 l))

it fails, and needs to be turned into

(define (g (l : (Listof Number)))
  : Number
  (foldl (λ ((x : Number) (y : Number)) (+ x y))  0 l))

This only happens when the anonymous function is being passed as an argument, as best I can see, as this (again, silly) function is OK:

(define (gg (x : Number) (y : Number))
  ((λ (a b) (+ a b))
   x y))

In this last function you can see from the GUI that it has successfully inferred the types of a and b from those of x and y.

It is easily possible that I am just confused about something here, however as I'm not even barely competent in Typed Racket.

So the question is: am I confused and the types of the arguments to these anonymous functions really are not knowable, or is it just the case that this is something that the type checker isn't (yet) smart enough to deduce on its own?


Solution

  • I'm not sure what you mean by "not knowable" but this is indeed how Typed Racket works. If you apply a polymorphic function, it does not use the types of the arguments to infer the types of the other arguments. But it does use the types of the arguments to infer the types of the parameters in the last example.