为什么我必须在此函数中包含额外的类型信息

时间:2015-10-18 13:09:11

标签: scala

我在业余时间尝试刷新一点Scala。我的问题是,为什么我必须注释' size'在这里使用多态类型A。当我计算树的大小时,我对这些信息不感兴趣。尽管如此,Scala编译器强迫我这样写:

def size[A](t: Tree[A]): Int = {
    t match {
      case Leaf => 1
      case Branch(l,r) => 1 + size(l) + size(r)
    }
}

而不是:

def size(t: Tree): Int = {
    t match {
      case Leaf => 1
      case Branch(l,r) => 1 + size(l) + size(r)
    }
}

此功能的上下文:

package fpinscala.datastructures

sealed trait Tree[+A]
case class Leaf[A](value: A) extends Tree[A]
case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]

object Tree {

  def size[A](t: Tree[A]): Int = {
    t match {
      case Leaf => 1
      case Branch(l,r) => 1 + size(l) + size(r)
    }
  }

}

2 个答案:

答案 0 :(得分:4)

首先注意你的功能有问题:

case Leaf => 1

Leaf伴侣对象相等而不是案例类匹配;你应该写一下:

case Leaf(_) => 1

然后您可以使用通配符存在类型来避免类型:

def size(t: Tree[_]): Int = {
  t match {
    case Leaf(_) => 1
    case Branch(l,r) => 1 + size(l) + size(r)
  }
}

另请注意,您的尺寸函数也会计算分支数量,我认为您更有可能只想数叶子;在这种情况下,将其更改为:

case Branch(l,r) => size(l) + size(r)

计算分支机构:

size(Branch(Branch(Leaf(1),Leaf(2)),Leaf(3))) = 5

计算叶子:

Branch(Branch(Leaf(1),Leaf(2)),Leaf(3)) = 3

答案 1 :(得分:0)

关于你的评论,你有这个:

object Tree {

  def size[A](t: Tree[A]): Int = {  //you would want to avoid specifying the first [A]
    t match {
      case Leaf => 1
      case Branch(l,r) => 1 + size(l) + size(r)
    }
  }

}

请注意,伴随对象不涉及泛型类型,因此必须在其方法上指定,否则编译器将搜索A class(在解析size的参数时),显然不存在。
您想告诉编译器: A是一种泛型类型,而不是特定类型

所以它不是一个样板,它是编译器需要的东西,它看起来很合乎逻辑。