在实现不可变数据类型时,在Scala中修剪类型信息

时间:2015-10-10 14:38:56

标签: scala

我想知道在Scala中编写简单的BST时是否有某种方法可以保持详细级别:

sealed class BST[K <: Ordered[K], V]    
final case class Empty[K <: Ordered[K], V]
final case class Node[K <: Ordered[K], V](key : K, value : V, left :  BST[K, V], right : BST[K, V])

object BST {
  def size[K <: Ordered[K], V](bst: BST[K, V]): Int = bst match {
    case Empty => 0
    case Node(_, _, left, right) => 1 + size(left) + size(right)
  }
}

F#中的等效定义类似于:

module BST =
  type t<K' : comparison, 'V> =
    | Empty
    | Node of K * V * t<K, V> * t<K, V>

  let rec size = function
    | Empty -> 0
    | Node(_, _, left, right) -> 1 + (size left) + (size right)

我发现特别有问题的是必须为所有函数重复关于通用参数和实际参数类型的相同yaddayadda。有没有办法减少这些东西?

1 个答案:

答案 0 :(得分:0)

一种选择是将函数定义为某些隐式融合类中的操作:

sealed class BST[K: Ordering, V]
final case class Empty[K: Ordering, V]() extends BST[K, V]
final case class Node[K: Ordering, V](key: K, value: V, left: BST[K, V], right: BST[K, V]) extends BST[K, V]


object BST {    
  import Ordering.Implicits._

  implicit class BSTOps[K: Ordering, V](val bst: BST[K, V]){
    def size: Int = bst match {
      case Empty() => 0
      case Node(_, _, left, right) => 1 + left.size + right.size
    }

    def :+(kv: (K, V)): BST[K, V] = {
      val (key, value) = kv
      bst match {
        case Empty() => Node(key, value, Empty(), Empty())
        case node@Node(nodeKey, _, _, _) => if (nodeKey > key)
          node.copy(left = node.left :+ kv)
        else node.copy(right = node.right :+ kv)

      }
    }
  }
}