Apologies for the messy title—my technical vocab is lacking, and I was unsure of how to phrase this. How can I identify an argument in Racket as being of a certain type, without knowing either
match)type? (such as integer?) that checks if it is the specified type?Specifically, imagine I have some function with the type (: fn : (All (a b c) (a -> c) (b -> c) (Listof (U a b)) -> Listof c)); we can imagine it being called as (fn fa fb xs). I would like this function to convert xs into a Listof c; it should do so by mapping each element x of xs to (fa x) if x is of type a, and (fb x) if x is of type b. For example, we might take in a list of strings and reals, and map the strings to their lengths, and the reals to the nearest integers.
In the specific case where I know that a is String and b is Real, I can write something like
(define (fn fa fb xs)
(map (lambda (x) (if (string? x) (fa x) (fb x))) xs))
But this works only if I have a known function string? to check the type of x.
Is it possible to do what I'm suggesting in Racket?
There's no "type of" operation in Typed Racket, so the answer is no. However, you can pass a "decider" to fn to select which function should be used to apply for each element.
The -> form allows you to specify propositions for occurrence typing, so you can write this code:
#lang typed/racket
(: fn (All (a b c)
((U a b) -> Boolean : a)
(a -> c)
(b -> c)
(Listof (U a b))
->
(Listof c)))
(define (fn decider fa fb xs)
(map (lambda ([x : (U a b)])
(if (decider x) (fa x) (fb x)))
xs))
Then you can invoke it:
(fn string? string-length add1 (list 1 "a" 23 "bc"))
;; '(2 1 24 2)
Thanks to Sam Tobin-Hochstadt for his help!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With