Scalaで集合(Set)

30分プログラム、その391。Programming in Scala, Third Editionが型パラメータのとこに入ったので、コンテナっぽいクラスが作ってみたくなった。なので、集合クラスを作ってみた。

ポイントは、

class MySet[T <: Ordered[T]]

としてるので、Ordered traitを持ってるやつしか、属性として持てないところ。

ただ、残念ながらIntとかStringはOrdered traitを持ってないので、このSetクラスには格納できない。RichIntとかはOrdered traitを持ってるけど、暗黙の型変換は行なわれないみたいだし・・。

# はてなシンタックスハイライト、Scalaに対応しないかなぁ

使い方

// 集合を作る
scala> val set1 = MySet(MyInt(1),MyInt(2))
set1: MySet[MyInt] = List(1, 2)

// 追加する
scala> val set2 = set1 + MyInt(10)
set2: MySet[MyInt] = List(1, 2, 10)

// 重複する要素は無視される
scala> val set3 = set2 + MyInt(1)
set3: MySet[MyInt] = List(1, 2, 10)

ソースコード

class MySet[T <: Ordered[T]](xs : List[T]) {
  def this() = 
    this(List())

  def +(x : T) : MySet[T] = 
    new MySet(insert(x,xs))

  private def insert(x : T, xs : List[T]) : List[T] = {
    xs  match {
      case Nil =>
	List(x)
      case y::ys =>
	if(x < y)
	  x::xs
	else if(x > y)
	  y::insert(x,ys)
	else
	  xs
    }
  }

  override def toString() =
    this.xs.toString()
}

object MySet{
  def apply[T <: Ordered[T]](xs : T*) = 
    xs.foldLeft(new MySet[T]())(_ + _)
}


class MyInt(val x : Int) extends Ordered[MyInt] {
  def compare(that : MyInt) =
    this.x - that.x

  override def toString() =
    x.toString

  def equals(that : MyInt) = 
    this.x equals that.x
}

object MyInt{
  def apply(x : Int) =
    new MyInt(x)
}