typed-racket icon indicating copy to clipboard operation
typed-racket copied to clipboard

A strange problem caused by `indexes-of`.

Open NoahStoryM opened this issue 3 years ago • 2 comments

What version of Racket are you using?

v8.4 [cs]

What program did you run?

Welcome to Racket v8.4 [cs].
> (require/typed racket/list
    [indexes-of (All (a b)
                     (case->
                      (-> (Listof a) Any (Listof Index))
                      (-> (Listof a) b (-> a b Any) (Listof Index))))])
> (indexes-of '(1 2 1 2 1) 2)
- : (Listof Index)
'()
> (indexes-of '(1 2 1 2 1) 2 equal?)
- : (Listof Index)
'(1 3)

To figure out why equal? doesn't compare values correctly, I tried the following code:

#lang typed/racket

(module untyped racket/base
  (provide (all-defined-out))
  (define (indexes-of ls v [=? equal?])
    (displayln (=? v 2))
    (let loop ([ls ls]
               [i 0])
      (cond [(null? ls) '()]
            [(=? (car ls) v) (cons i (loop (cdr ls) (add1 i)))]
            [else (loop (cdr ls) (add1 i))]))))

(require/typed 'untyped
  [indexes-of (All (a b)
                   (case->
                    (-> (Listof a) Any (Listof Index))
                    (-> (Listof a) b (-> a b Any) (Listof Index))))])
(indexes-of '(1 2 1 2 1) 2)
(indexes-of '(1 2 1 2 1) 2 =)

What should have happened?

#t
'(1 3)
#t
'(1 3)

If you got an error message, please include it here.

#t
'()
indexes-of: broke its own contract
  promised: a4
  produced: #<b5>
  in: the 1st argument of
      the 3rd argument of
      the 2nd case of
      (parametric->/c
       (a4 b5)
       (case->
        (-> (listof a4) any-wrap/c (values g7))
        (->
         (listof a4)
         b5
         (->* (a4 b5) () (values any-wrap/c))
         (values g7))))
  contract from: (interface for indexes-of)
  blaming: (interface for indexes-of)
   (assuming the contract is correct)
  at: /home/noah/Desktop/Codes/Racket/draft0.rkt:14:3
  context...:
   /usr/share/racket/collects/racket/contract/private/blame.rkt:346:0: raise-blame-error
   /usr/share/racket/collects/racket/contract/private/arrow-higher-order.rkt:369:33
   /home/noah/Desktop/Codes/Racket/draft0.rkt:5:2: indexes-of
   body of "/home/noah/Desktop/Codes/Racket/draft0.rkt"

NoahStoryM avatar Mar 27 '22 10:03 NoahStoryM

I think the problem should be caused by require/typed. After I add the types in base-env.rkt (https://github.com/racket/typed-racket/pull/1215), it works fine:

Welcome to Racket v8.4 [cs].
> (indexes-of '(1 2 1 2 1) 2)
- : (Listof Index)
'(1 3)
> (indexes-of '(1 2 1 2 1) 2 equal?)
- : (Listof Index)
'(1 3)
> (indexes-where '(1 2 1 2 1) (curry equal? 2))
- : (Listof Index)
'(1 3)

And unsafe-require/typed also works fine:

Welcome to Racket v8.4 [cs].
> (require typed/racket/unsafe)
> (unsafe-require/typed racket/list
      [indexes-of (All (a b)
                       (case->
                        (-> (Listof a) Any (Listof Index))
                        (-> (Listof a) b (-> a b Any) (Listof Index))))])
> (indexes-of '(1 2 1 2 1) 2)
- : (Listof Index)
'(1 3)

NoahStoryM avatar Mar 27 '22 10:03 NoahStoryM

There are a few things to say here.

  1. The easiest thing to do is to use (Listof Any) as the type of the first argument.
  2. The initial problem is because contracts for polymorphic types seal their values; they can't be used except by moving them around or passing them to a function argument.
  3. The problem in your implementation is the display; take that out and it will work.

samth avatar Mar 28 '22 16:03 samth