Types 在键入的racket中对集合列表使用apply时出现奇怪的typechecker行为

Types 在键入的racket中对集合列表使用apply时出现奇怪的typechecker行为,types,racket,typed-racket,Types,Racket,Typed Racket,我有一个集合列表,我想把这些集合合并起来 类似于下面的内容 (apply set-union (list (set 'a) (set 'b))) 它可以工作并给出正确的结果(设置“a”和“b”) 现在,如果我尝试像这样编写相同的代码: (: l (Listof (Setof Symbol))) (define l (list (set 'a) (set 'b))) (apply set-union l) 然后我得到以下错误: Type Checker: Bad arguments to fu

我有一个集合列表,我想把这些集合合并起来

类似于下面的内容

(apply set-union (list (set 'a) (set 'b)))
它可以工作并给出正确的结果(设置“a”和“b”)

现在,如果我尝试像这样编写相同的代码:

(: l (Listof (Setof Symbol)))
(define l (list (set 'a) (set 'b)))
(apply set-union l)
然后我得到以下错误:

Type Checker: Bad arguments to function in `apply':
  Domains: (Listof e)(Listof e) *
           (Setof e)(Setof e) *
  Arguments: (Listof (Setof Symbol))
如何将集合并集函数应用于集合列表


我应该提到,同一段代码适用于非类型的racket语言或使用语言,这就是为什么我认为这肯定是一个类型检查问题。

错误消息指出,涉及集合的函数域是
(Setof e)(Setof e)*
,这意味着
set union
至少需要一个参数才能正确应用
(Listof(Setof Symbol))
可能是空列表,这将导致运行时错误


因此,您应该给
l
一个更具体的类型。您可以使用
(List(Setof Symbol)(Setof Symbol))
来最精确地描述它,或者如果您只需要一个类型来捕获“至少包含一个元素的集合列表”的概念,您可以使用类型
(Pairof(Setof Symbol)(Listof(Setof Symbol))

@Alexis King的诊断是正确的,如果您知道输入列表不是空的,那么她建议对输入列表使用更具体的类型是一个很好的建议。但是,在某些情况下,无法更改输入列表的类型:有时列表是空的,您必须处理它

当列表为空时,您需要一个空集,因此除了列表之外,您还可以对空集应用
set union

(define l (list))
(apply set-union (set) l)
;=> (set)
即使
l
具有原始类型
(Listof(Setof Symbol))
且可以为空,这也会使键入的Racket接受联合:

(: l (Listof (Setof Symbol)))
(define l (list (set 'a) (set 'b)))
(apply set-union (set) l)
;=> (set 'a 'b)
要确保结果类型可以是特定的,以便联合可以是
(集合符号)
,您应该确保
(集合)
至少有一个特定的类型。在这种情况下,空集的类型可以是
(Setof Nothing)
,因此您可以使用
((inst set Nothing))


如果希望结果是有用的类型,例如
(:result(Setof Symbol))
,则必须键入强制转换(set),例如
(define result(apply set union(cast(set)(Setof Symbol))l))
。否则它会默认为
(Setof Any)
哦,谢谢你的关注。尽管您不应该在这里使用
cast
,因为这会变成合同检查。改用
ann
inst
。在这种情况下,您可以像在
((inst set Nothing))
中一样使用
inst
,以便联合的结果是
(Setof Symbol)
(: l (Listof (Setof Symbol)))
(define l (list (set 'a) (set 'b)))
(apply set-union ((inst set Nothing)) l)
;- : (Setof Symbol)
;=> (set 'a 'b)