Hello,
I need to pass a function of unknown arity to another function in Typed Racket, in particular because the approach using polymorphic functions from this thread does not completely fit my use case, and also because I don't know how to write this type (-> Boolean ... Boolean)
correctly.
I tried writing untyped code and adding a type a posteriori:
#lang typed/racket
(module untyped racket
(provide do)
(define (do f x) (f x)))
(require/typed 'untyped
[do (-> Procedure Any Any)]
)
(do (λ (x) x) 2)
This gives the following error:
; g5: arity mismatch;
; the expected number of arguments does not match the given number
; given: 1
Indeed, the documentation for Procedure
says:
Because this type encodes only the fact that the value is a procedure, and not its argument types or even arity, the type-checker cannot allow values of this type to be applied.
I hoped that this constraint would not propagate over to untyped code, but obviously I was wrong. Also, this means that Procedure
cannot be used as a direct replacement for procedure?
.
If I replace the type of do
by (-> Any Any Any)
, I get the following error:
; Attempted to use a higher-order value passed as `Any` in untyped code
I also tried (All (b a ...) (-> (-> a ... b) Any Any))
as the type for do
, but this of course gives me:
Type Checker: Type (All (b a ...) (-> (-> a ... a b) Any Any)) could not be converted to a contract: cannot generate contract for variable arity polymorphic type
Finally, the type (-> (-> Any Any) Any Any)
works obviously, but I need to pass a function of unknown arity as the first parameter.
Is there a way to pass a function of unknown arity across the typed/untyped boundary?
Alternatively, for my use case, is there a way to write the type (-> Boolean ... Boolean)
?