Mixin composition in typed racket

33 views
Skip to first unread message

hashim....@gmail.com

unread,
Nov 14, 2020, 5:58:45 AM11/14/20
to Racket Users
Hi,

I'm trying to go from a small racket program that uses classes to a typed racket version of the program, but I can't find a combination of types that works. (The untyped version works as intended.)

Specifically, if I have a recipe% class, and an amount-mixin and unit-mixin , and each of these 3 have 1-argument init specifiers, how do I add types to both mixins such that (amount-mixin (unit-mixin recipe%)) works? (edited) 

The untyped version:

    #lang racket/base
     
    (require racket/class)
     
     
    (define recipe%
      (class object%
        (init name #;steps )
        (super-new)
        (define _name name)
        ;(define _steps steps)
        ;(define/public (get-steps) _steps)
        (define/public (get-name) _name)))
     
     
    (define (amount-mixin %)
      (class %
        (init amount)
        (define _amount amount)
        (super-new)
        (inherit get-name)
        (define/public (get-amount) _amount)))
     
     
    (define (unit-mixin %)
      (class %
        (init unit)
        (define _unit unit)
        (super-new)
        (inherit get-name)
        (define/public (get-unit) _unit)))
     
     
    (unit-mixin (amount-mixin recipe%))


And the typed version (that raises an error):

#lang typed/racket/base

(require typed/racket/class)


(define-type recipe<%>
  (Class (init [name String])
         (get-name (-> String))))
(: recipe% recipe<%>)
(define recipe%
  (class object%
    (init [name : String])
    (super-new)
    (: _name String)
    (define _name name)
    (define/public (get-name) _name)))


(: amount-mixin (->  recipe<%>
                     (Class #:implements recipe<%>
                            (init [amount Number]
                                  [name String])
                            (get-amount (-> Number)))))
(define (amount-mixin %)
  (class %
    (init [amount : Number])
    (: _amount Number)
    (define _amount amount)
    (super-new)
    (inherit get-name)
    (define/public (get-amount) _amount)))


(: unit-mixin (-> recipe<%> (Class #:implements recipe<%>
                                   (init [unit String]
                                         [name String])
                                   (get-unit (-> String)))))
(define (unit-mixin %)
  (class %
    (init [unit : String])
    (: _unit String)
    (define _unit unit)
    (super-new)
    (inherit get-name)
    (define/public (get-unit) _unit)))


(unit-mixin (amount-mixin recipe%))


Any advice on how to make this work? Or whether to simply not do this in typed racket?

Regards,
Hashim.

Asumu Takikawa

unread,
Nov 17, 2020, 5:10:33 PM11/17/20
to hashim....@gmail.com, Racket Users
On 2020-11-14 02:58:44 -0800, hashim....@gmail.com wrote:
> Any advice on how to make this work? Or whether to simply not do this in
> typed racket?

It's possible to do this in Typed Racket but it's just a bit more
cumbersome as you need to make the function type row-polymorphic. Here's
a version that should typecheck:

;;;

#lang typed/racket/base

(require typed/racket/class)

(define-type recipe<%>
(Class (init [name String])
(get-name (-> String))))

(: recipe% recipe<%>)
(define recipe%
(class object%
(init [name : String])
(super-new)
(: _name String)
(define _name name)
(define/public (get-name) _name)))


(: amount-mixin (All (r #:row)
(-> (Class #:implements recipe<%>
#:row-var r)
(Class #:implements recipe<%>
#:row-var r
(init [amount Number])
(get-amount (-> Number))))))
(define (amount-mixin %)
(class %
(init [amount : Number])
(: _amount Number)
(define _amount amount)
(super-new)
(inherit get-name)
(define/public (get-amount) _amount)))


(: unit-mixin (All (r #:row)
(-> (Class #:implements recipe<%>
#:row-var r)
(Class #:implements recipe<%>
#:row-var r
(init [unit String])
(get-unit (-> String))))))
(define (unit-mixin %)
(class %
(init [unit : String])
(: _unit String)
(define _unit unit)
(super-new)
(inherit get-name)
(define/public (get-unit) _unit)))


(unit-mixin (amount-mixin recipe%))

;;;

Cheers,
Asumu
Reply all
Reply to author
Forward
0 new messages