简体   繁体   中英

Typed Racket type for list of functions representing pipeline

I have a function in untyped Racket that takes arguments representing an input, a list of functions and symbols that represent a pipeline, and a symbol to stop applying functions before (I know that's not very clear but the code is beneath). I'm trying to convert it to Typed Racket, but can't figure out how to get the type system to understand what's going on. I know I can just use cast to force it to work, but I wonder if there is a better way?

(define (apply-steps on steps stop-symbol)
  (match steps
    ['() on]
    [(cons step rst)
     (cond
       [(equal? stop-symbol (car step)) ((cadr step) on)]
       [else (apply-steps ((cadr step) on) rst stop-symbol)])]))

I need to somehow specify a type for the signature something like:

(apply-steps [on : T1] 
             [steps : (List (Pairof Symbol (-> T1 T2)) (Pairof Symbol (-> T2 T3)) ... (Pairof Symbol (-> Tn-1 Tn))]
             [stop-symbol : Symbol]) : Tn

Thanks!

There are a couple of problems:

  • One of your inputs is essentially a list of functions. You want it to have type (List (-> F1 F2) (-> F2 F3)... (-> Fn Fn+1)) , but I don't think Typed Racket can support this kind of things. If you write it out, it involves unbounded number of type variables, depending on the length of the list? How can you even finitely specify the type.[1].

    To workaround this, I suggest you changing the requirement to (List (-> AA) (-> AA)... (-> AA)) = (Listof (-> AA)) .

  • According to the given type, each element is a (Pairof Function Symbol) , but from your function, it looks like it expects a (List Symbol Function) (this is caught of Typed Racket when I tried out your program).

Applying the fixes, you would get:

(: apply-steps (All (A) (-> A (Listof (List Symbol (-> A A))) Symbol A)))
(define (apply-steps on steps stop-symbol)
  (match steps
    ['() on]
    [(cons step rst)
     (cond
       [(equal? stop-symbol (car step)) ((cadr step) on)]
       [else (apply-steps ((cadr step) on) rst stop-symbol)])]))

By the way, if you use regular Racket, you can just use for/fold with a #:final clause to implement this function too.

(define (apply-steps on steps stop-symbol)
  (for/fold ([on on]) ([step (in-list steps)])
    (match-define (list sym f) step)
    #:final (equal? stop-symbol sym)
    (f on)))

Unfortunately, #:final is not supported by Typed Racket (yet), so you can't use it here.

[1]: OK, so one possibility might be: for any two adjacent elements in the list, they must be (-> AB) and (-> BC) for some A , B , C . Still, I don't think Typed Racket can support arbitrary higher-order predicate like this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM