标准ML中一组集上的类型冲突问题

时间:2011-07-29 18:54:52

标签: ml sml

我正在阅读在线书籍“计算类别理论”http://www.cs.man.ac.uk/~david/categories/book/book.pdf,我在本书中遇到了问题2.10的一些问题。特别是有了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

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

为什么我可以计算一组整数的基数,而不是一组整数的基数?我做错了吗?

1 个答案:

答案 0 :(得分:0)

麻烦在于你如何计算集合的基数。

为了计算集合的基数,您需要遍历每个元素,删除它以及同一元素的所有其他元素,每次删除都会增加一个计数。

特别是,“同一元素的所有进一步出现”部分都是失败的。

int类型是一个相等类型,因此在这种情况下比较两个整数以查看它们是否相同可以很好地运作。

但是,int Set类型不是相等类型。这意味着,list_remove调用无效,因为它无法比较两个int Set

为什么这样,你可能会问?好吧,请考虑以下事项:

val onlythree = singleton 3; (* {3} *)
val onlythree_2 = union (onlythree, onlythree); (* {3} U {3} = {3} *)

这两个集合都代表相同的集合,但内部表示不同:

onlythree   = set [3]
onlythree_2 = set [3, 3]

因此,如果您允许标准相等运算符直接在这些运算符上运行,那么即使它们代表相同的集合,您也会得到它们不同的结果。这不好。

解决这个问题的一种方法是,每当从设置操作返回结果时,确保集合始终由其“规范表示”表示。不过,我不确定这是否可行。