[racket-dev] A more useful struct type predicate for structs with contravariant blah-de-blah?

From: Neil Toronto (neil.toronto at gmail.com)
Date: Fri Aug 24 19:29:41 EDT 2012

A while ago, on PR 12903 (I don't know why it's not closed yet, FWIW, 
because I think it's fixed), we had this discussion:

Me: I think this should work.

#lang typed/racket

(struct: (A) bar ([proc : (A -> Any)]))
(define-predicate -bar? (bar Any))

Sam: That's evil; here's why. Suppose `bar` had a predicate with type 
(Any -> Boolean : (bar Any)). You could do this:

(define: v : Any (bar (lambda: ([x : Integer]) (add1 x))))
(when (my-bar? v) ;; check that `v` is a `(bar Any)`
   (define: f : (Any -> Any) (bar-proc v)) ;; type-correct: A = Any
   (f "not an integer"))

Me: Got it. [Consults this answer every time it comes up, because he 
forgets why a useful `bar?' predicate is bad.]

So here's my latest question. Say we have these definitions:

#lang typed/racket

(struct: (A) foo ())
(struct: (A) bar foo ([proc : (A -> Any)]))

Could `bar?' have the type (All (A) ((foo A) -> Boolean : (bar A)))? 
Then (I think), something like this should type:

(: maybe-foo-proc (All (A) ((foo A) -> (U #f (A -> Any)))))
(define (maybe-foo-proc v)
   (if (bar? v) (bar-proc v) #f))

(Well, it wouldn't currently; the error is "Expected (bar A); given 
#(struct:#<syntax:4:13 bar> ((Nothing -> Any)))".)

Is that also evil? I hope not, because the useless type of `bar?' is 
precluding a possibly important performance enhancement.

Neil ⊥

Posted on the dev mailing list.