[racket] occurrence typing for case?

From: Eric Dobson (eric.n.dobson at gmail.com)
Date: Sun May 11 19:41:41 EDT 2014

On Sun, May 11, 2014 at 4:10 PM, Alexander D. Knauth
<alexander at knauth.org> wrote:
> It seems like case doesn’t do occurrence typing, when it seems like it would
> be easiest for case, because of singleton types.
> For example:
> #lang typed/racket
>
> (define (f x)
>   (case x
>     [(thing) (g x)]
>     ))
>
> (: g ('thing -> 'thing))
> (define (g x) x)
>
> Gives me this:
> . Type Checker: type mismatch
>   expected: 'thing
>   given: Any in: x
>
> This isn’t much of a problem (I can easily just do a cast), but It just
> seems like it should be really easy for typed racket to figure out that x
> has the type ‘thing if it gets into that clause.
The issue is that there is a temporary variable that has the same
value as x and TR cannot see that they point to the same location.
Your implementation of case/type has the same problem. I thought there
was a bug filed for it but couldn't find it so just filed one.
http://bugs.racket-lang.org/query/?cmd=view&pr=14502

>
> By the way is there something like case/type that would be something like
> this?:
> (case/type x
>   [Type-1 body …]
>   [Type-2 body …]
>>   )
> And would use (make-predicate Type) to do it so that it would do occurrence
> typing?  Maybe something like this:
> (define-syntax-rule
>   (case/type x-expr
>     [t body …] …)
>   (let ([x x-expr])
>     (cond [((make-predicate t) x) body …] …))
>   )
>
> I tried it, but it didn’t work like I expected it to do with occurrence
> typing:
> #lang typed/racket
> (require typed/rackunit)
>
> (define-syntax-rule
>   (case/type x-expr
>     [t1 body ...] ...)
>   (let ([x x-expr])
>     (cond [((make-predicate t1) x) body ...] ...))
>   )
>
> (define (my-length x)
>   (case/type x
>     [String (string-length x)]
>     [(Listof Any) ((inst length Any) x)]
>     [VectorTop (vector-length x)]
>     ))
> (check-equal? (my-length "12345") 5)
> (check-equal? (my-length '(1 2 3 4 5)) 5)
> (check-equal? (my-length #(1 2 3 4 5)) 5)
>
> It gave me these errors:
> . Type Checker: type mismatch
>   expected: String
>   given: Any in: x
> . Type Checker: type mismatch
>   expected: (Listof Any)
>   given: Any in: x
> . Type Checker: type mismatch
>   expected: VectorTop
>   given: Any in: x
>
> So I guess it didn’t do occurrence typing for that either, even though it
> uses make-predicate.  Is there anything I can do to help it do occurrence
> typing for this?

Use this:
#lang typed/racket
(require typed/rackunit)

(define-syntax-rule
  (case/type y x-expr
    [t1 body ...] ...)
  (let ([y x-expr])
    (cond [((make-predicate t1) y) body ...] ...))
  )

(define (my-length x)
  (case/type y x
    [String (string-length y)]
    [(Listof Any) (length y)]
#;
    [VectorTop (vector-length y)]
    ))
(check-equal? (my-length "12345") 5)
(check-equal? (my-length '(1 2 3 4 5)) 5)
#;
(check-equal? (my-length #(1 2 3 4 5)) 5)

There is currently an issue with generating the predicate for VectorTop.

>
> By the way why is length polymorphic?
Not sure if there is any reason, most list functions are so likely
because the original author was just writing a bunch of them at once.


>
>
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users
>


Posted on the users mailing list.