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)