rackettyped-racket

Adding type annotations to classes in racket


Trying to finish up an implementation of Conway's Game of Life in Racket and I'm adding types to everything. I'm having trouble figuring out what exactly I need to do to get the classes from the gui lib typed correctly.

(: new-timer (Instance Timer%))
(define new-timer (new timer% [interval 400]
                       [notify-callback (lambda () (begin
                                                     (set-field! grd cv (next-grid (get-field grd cv) ROW COLUMNS))
                                                     (send cv on-paint)))]))
(: new-canvas% Canvas%)
(define new-canvas% (class canvas%
              (super-new)
              (inherit get-dc suspend-flush resume-flush)
              (field [dc : (Instance DC<%>) (get-dc)] [grd : Grid (make-grid ROW COLUMNS)])
              (define/override (on-char char)
            (let ([event (send char get-key-code)])
              (cond

                            [(and (char? event) (char=? event #\space)) (send new-timer stop)])))


                      (define/override (on-paint)
                        (send dc erase)
                        (suspend-flush)
                        (render-grid grd ROW COLUMNS dc)
                        (resume-flush))))

(: cv (Instance Canvas%))
(define cv (new new-canvas% [parent main-frame]))

I'm getting this error below

/Documents/conways-game-of-life/main.rkt:49:83: Type Checker: type mismatch;
;  the object is missing an expected field
;   field: grd
;   object type: (Instance Canvas%)
;   in: (get-field grd cv)
; Context:
;  /usr/share/racket/collects/racket/promise.rkt:128:5
; /home/diego/Documents/conways-game-of-life/main.rkt:49:53: Type Checker: type mismatch;
;  expected an object with field grd
;   given: (Instance Canvas%)
;   in: (set-field! grd cv (next-grid (get-field grd cv) ROW COLUMNS))

I think it because canvas doesn't normally have a grd field but every time I try to give my canvas the type declaration (: cv (Instance new-canvas%)) It says it's unbound. Full file and all code can be found here. Does anyone have any ideas?


Solution

  • In the definition of new-timer, you're trying to get the grd field of cv.

    And although cv is an instance of the class new-canvas%, its type does not include that field. You need to create a new Class type for new-canvas%. By convention, it should be a capitalized version like New-Canvas%.

    (define-type New-Canvas% (Class ....))
    
    (: new-canvas% New-Canvas%)
    (define new-canvas% (class ....))
    
    (: cv (Instance New-Canvas%))
    (define cv (new .....))
    

    The New-Canvas% type you define using Class should specify the new field grd, as well as specifying that it's a subclass of Canvas%.