StandardML 中一组集合的类型冲突问题
我正在阅读在线书籍“计算类别理论”http:// /www.cs.man.ac.uk/~david/categories/book/book.pdf 我在本书中的问题 2.10 中遇到了一些问题。特别是幂集的定义。
abstype 'a Set = set of 'a list
with val emptyset = set([])
fun is_empty(set(s)) = length(s)=0
fun singleton(x) = set([x])
fun disjoint_union(set(s),set(nil))=set(s) |
disjoint_union(set(s),set(t::y))=
if list_member(t,s) then disjoint_union(set(s),set(y))
else disjoint_union(set(t::s),set(y))
fun union(set(s),set(t)) = set(append(s,t))
fun member(x,set(l)) = list_member(x,l)
fun remove(x,set(l)) = set(list_remove(x,l))
fun singleton_split(set(nil)) = raise empty_set
| singleton_split(set(x::s)) =(x,remove(x,set(s)))
fun split(s) = let val (x,s') = singleton_split(s) in (singleton(x),s') end
fun cardinality(s) = if is_empty(s) then 0 else
let val (x,s') = singleton_split(s) in 1 + cardinality(s') end
fun image(f)(s) = if is_empty(s) then emptyset else
let val (x,s') = singleton_split(s) in
union(singleton(f(x)),image(f)(s')) end
fun display(s)= if is_empty(s) then [] else
let val (x,s') = singleton_split(s) in x::display(s') end
fun cartesian(set(nil),set(b))=emptyset |
cartesian(set(a),set(b)) = let val (x,s') = singleton_split(set(a))
in union(image(fn xx => (x,xx))(set(b)),cartesian(s',set(b))) end
fun powerset(s) =
if is_empty(s) then singleton(emptyset)
else let
val (x,s') = singleton_split(s)
val ps'' = powerset(s')
in union(image(fn t => union(singleton(x),t))(ps''),ps'') end
end
powerset 函数由附录 D 中的答案给出。然后我创建一个集合的 powerset:
val someset=singleton(3); (*corresponds to the set {3}*)
val powerset=powerset(someset); (* should result in {{},{3}} *)
val cardinality(someset); (*returns 1*)
val cardinality(powerset); (*throws an error*)
! Type clash: expression of type
! int Set Set
! cannot have type
! ''a Set
为什么我可以计算一组整数的基数,但不能计算一组整数的基数?我做错了什么吗?
I am perusing the online book "Computational Category Theory" http://www.cs.man.ac.uk/~david/categories/book/book.pdf and I am having some problems with problem 2.10 in this book. Particularly, with the definition of the powerset.
abstype 'a Set = set of 'a list
with val emptyset = set([])
fun is_empty(set(s)) = length(s)=0
fun singleton(x) = set([x])
fun disjoint_union(set(s),set(nil))=set(s) |
disjoint_union(set(s),set(t::y))=
if list_member(t,s) then disjoint_union(set(s),set(y))
else disjoint_union(set(t::s),set(y))
fun union(set(s),set(t)) = set(append(s,t))
fun member(x,set(l)) = list_member(x,l)
fun remove(x,set(l)) = set(list_remove(x,l))
fun singleton_split(set(nil)) = raise empty_set
| singleton_split(set(x::s)) =(x,remove(x,set(s)))
fun split(s) = let val (x,s') = singleton_split(s) in (singleton(x),s') end
fun cardinality(s) = if is_empty(s) then 0 else
let val (x,s') = singleton_split(s) in 1 + cardinality(s') end
fun image(f)(s) = if is_empty(s) then emptyset else
let val (x,s') = singleton_split(s) in
union(singleton(f(x)),image(f)(s')) end
fun display(s)= if is_empty(s) then [] else
let val (x,s') = singleton_split(s) in x::display(s') end
fun cartesian(set(nil),set(b))=emptyset |
cartesian(set(a),set(b)) = let val (x,s') = singleton_split(set(a))
in union(image(fn xx => (x,xx))(set(b)),cartesian(s',set(b))) end
fun powerset(s) =
if is_empty(s) then singleton(emptyset)
else let
val (x,s') = singleton_split(s)
val ps'' = powerset(s')
in union(image(fn t => union(singleton(x),t))(ps''),ps'') end
end
The powerset function is given from the answers in Appendix D. I then create the powerset of a set:
val someset=singleton(3); (*corresponds to the set {3}*)
val powerset=powerset(someset); (* should result in {{},{3}} *)
val cardinality(someset); (*returns 1*)
val cardinality(powerset); (*throws an error*)
! Type clash: expression of type
! int Set Set
! cannot have type
! ''a Set
Why can I calculate the cardinality of a set of integers, but not of a set of sets of integers? Am I doing something wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题在于如何计算集合的基数。
为了计算集合的基数,您需要遍历每个元素,删除它以及同一元素的所有其他出现,每次删除将计数加一。
特别是,“以及同一元素的所有进一步出现”部分是失败的。
int
类型是一种相等类型,因此在这种情况下,比较两个整数以查看它们是否相同效果很好。然而,
int Set
类型不是相等类型。这意味着list_remove
调用将不起作用,因为它无法比较两个int Set
。您可能会问这是为什么?好吧,考虑以下内容:
这两个集合都表示相同的集合,但内部表示不同:
因此,如果您允许标准相等运算符直接对它们进行操作,您会发现它们会有所不同,即使它们代表同一个集合。那可不好。
解决这个问题的一种方法是确保每当您从集合操作返回结果时,集合始终由其“规范表示”表示。不过,我不确定这通常是否可行。
The trouble lies in how you count the cardinality of the set.
In order to count the cardinality of the set, you go through each element, remove it as well as all further occurrences of the same element, increasing the count by one for each such removal.
In particular, the "as well as all further occurrences of the same element" part is what is failing.
The
int
type is an equality type, so in that case comparing two integers to see if they're the same works out well.The
int Set
type, however, is not an equality type. This means, thelist_remove
call will not work, as it cannot compare twoint Set
s.Why is this, you might ask? Well, consider the following:
These two sets both represent the same set, however the internal representations differ:
So, if you allowed the standard equality operator to work directly on these, you'd get that they'd be different, even though they represent the same set. That's no good.
One way of remedying this could be ensuring that a set always is represented by its "canonical representation" whenever you return a result from a set operation. I'm not sure if this is possible to do in general, however.