Getting the type of a (class) expression

Hi,

Consider the following typed class definition:

(define my-class
  (class object%
    (super-new)
    (init-field [x : Integer])
    (define/public (get-x) x)))

I can easily get the type of this class in the REPL:

> my-class
- : (Class (init (x Integer)) (field (x Integer)) (get-x (-> Integer)))
#<class:my-class>

I would like to give a name to this class expression, so that I can have a shorter version. I can obviously write the following:

(define-type MyClassType (Class (init (x Integer)) (field (x Integer)) (get-x (-> Integer))))

but this would mean that I'd need to do some copying and pasting every time I change my-class.

Is there a better way to define this type synonym?

More generally, is there a way to get the type of an expression?

As an example, I would like to be able to write something like:

(define x ...)
(define-type TypeOfX (get-type x))
1 Like

There must be a way to get the type of a class because typed Racket manages to figure it out internally.

That said, I'm no further along than you.
I'm trying to get the type of the objects in a class.
The obvious notation is just to use the name of the class as the type of its objects. In your case that would be 'my-class', but that diesn't work. Classes are run-time values.
I can write (Object (init (x Integer)) (field (x Integer)) (get-x (-> Integer)))
much like what you have done, but that has the same probems you have.

1 Like

Thank you for your message @hendrikboom3 , I am happy to not be the only one bugged by this question :smiley:

I always hesitate to tag people working on Typed Racket when writing such messages, but maybe I should to help them see the post?..

you can use :print-type to print the type of a value, but looking at its implementation, it seems to use the internal representation of the types which would not be suitable for use directly from Typed Racket programs.

I suspect there is no get-type facility in Typed Racket and I am not sure that it would be easy to implement.

On the other hand, I am not sure that defining types in terms of values is a good idea. If you had a get-type function and you define types such as (define-type TypeOfX (get-type x)), the actual type will silently change when the implementation of x changes, which might not be what the programmer intended and could hide programming errors.

Alex.

1 Like

Indeed. In particular, the docs are clear about the fact that :print-type only works in the REPL.

You are right, and I started realizing it after sending the message. On the other hand, the first question of having a shortcut for a class/instance type is still valid in the following sense. Typed structs introduce a type name, which you can then use in function types, etc. Typed structs even have the #:type-name argument which allows changing the type name. I have so far managed to find no such thing for classes. For example, the following does not work:

(: frobnicate (-> my-class% Void))
(define (frobnicate x) (void))
; /home/scolobb/Candies/prj/racket/dds/tmp.rkt:9:18: Type Checker: parse error in type;
;  type name `my-class%' is unbound
;   in: my-class%

Consider in contrast a typed struct:

(struct test ([x : Integer]))

(: frobnicate-struct (-> test Void))
(define (frobnicate-struct x) (void))

I can of course make frobnicate work by spelling out the full type (Instance (Class … )), or by defining a type synonym for this expression (that's what I do now), but it would be immensely practical to just have that type synonym out of the box, like it already happens with typed structs.