当参数类型为联合类型时,判断Racket中参数的具体类型

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

对于乱七八糟的标题,我深表歉意——我缺乏技术词汇,我不确定如何表达。我如何在不知道任何一个的情况下将 Racket 中的参数识别为某种类型

具体来说,假设我有一些类型为 (: fn : (All (a b c) (a -> c) (b -> c) (Listof (U a b)) -> Listof c)) 的函数;我们可以想象它被称为 (fn fa fb xs)。我希望此函数将 xs 转换为 Listof c;它应该通过将 xs 的每个元素 x 映射到 (fa x) 如果 x 是类型 a,如果 (fb x) 如果 [=18] =] 的类型为 b。例如,我们可能会接受一个字符串和实数列表,并将字符串映射到它们的长度,将实数映射到最接近的整数。

在我知道 aString 并且 bReal 的特定情况下,我可以写类似

(define (fn fa fb xs)
    (map (lambda (x) (if (string? x) (fa x) (fb x))) xs))

但这只有在我有一个已知函数 string? 来检查 x 的类型时才有效。

是否可以按照我在 Racket 中的建议进行操作?

Typed Racket 中没有“type of”操作,所以答案是否定的。但是,您可以将“决定器”传递给 fn 到 select 应使用哪个函数来申请每个元素。

-> form allows you to specify propositions for occurrence typing,所以可以这样写代码:

#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))

然后就可以调用了:

(fn string? string-length add1 (list 1 "a" 23 "bc"))

;; '(2 1 24 2)

感谢 Sam Tobin-Hochstadt 的帮助!