Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

for/list annotations in typed/racket

I'm trying to add types to some numerical racket code in the hopes of making it faster, but I am stuck dealing with for/list macro expansion in the code below.

(: index-member ((Listof Any) (Listof Any) -> (Listof Index)))
(define (index-member xs ys)
  (filter-not negative?
              (for/list ([(ann i Index) (in-range (ann (length xs) Index))])
                (if (member (list-ref xs i) ys) i -1))))

This function returns a list of indexes foreach x which is a member of y. It works in Racket, but I can't seem to get it past the type checker for Typed Racket. Specifically, the error is:

Type Checker: Error in macro expansion -- insufficient type information to typecheck. please add more type annotations in: (for/list (((ann i Index) (in-range (ann (length xs) Index)))) (if (member (list-ref xs i) ys) i -1))

Can you provide annotations that get this past the type checker and/or explain why these type annotations are insufficient?

like image 955
wdkrnls Avatar asked Aug 29 '13 14:08

wdkrnls


People also ask

What is typed racket?

Typed Racket is Racket's gradually-typed sister language which allows the incremental addition of statically-checked type annotations. This guide is intended for programmers familiar with Racket. For an introduction to Racket, see The Racket Guide. For the precise details, also see The Typed Racket Reference.

Are typed rackets faster?

Typed Racket provides a type-driven optimizer that rewrites well-typed programs to potentially make them faster. It should in no way make your programs slower or unsafe. Thus the type hinting can make your programs faster, but it guarantees the programs wont be slower than #lang racket as well.


1 Answers

The key is to use the for/list: form instead since it allows you to add type annotations over the basic for/list form to give Typed Racket more guidance. I've made a few other adjustments to get the types to line up (e.g., using filter over filter-not, avoiding in-range, etc.):

#lang typed/racket

(: index-member ((Listof Any) (Listof Any) -> (Listof Index)))
(define (index-member xs ys)
  (filter index?
          (for/list: : (Listof Integer) ([i : Index (length xs)])
            (if (member (list-ref xs i) ys) i -1))))

This actually exposes a weakness in the type of filter-not (filter is smarter about the type of the list it returns), which I'll look into fixing.

like image 158
Asumu Takikawa Avatar answered Sep 24 '22 01:09

Asumu Takikawa