Michael
Michael

Reputation: 153

Determine the specific type of an argument in Racket when the argument's type is a union type

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

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?

Upvotes: 4

Views: 800

Answers (1)

Sorawee Porncharoenwase
Sorawee Porncharoenwase

Reputation: 6502

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!

Upvotes: 4

Related Questions