【问题标题】:scala: type mismatch error - found T, required Stringscala:类型不匹配错误 - 找到 T,需要字符串
【发布时间】:2019-09-01 20:30:47
【问题描述】:

我正在学习scala,这个问题可能很愚蠢,但是......为什么?

例如这样就可以了:

def matchList(ls: List[Int]): List[Int] = ls match {
  case 1 :: rest => rest
  case a :: b :: rest => (a + b) :: rest
  case _ => ls
}

matchList: (ls: List[Int])List[Int]

但是带有类型参数的函数无法编译:

def matchList[T](ls: List[T]): List[T] = ls match {
  case 1 :: rest => rest
  case a :: b :: rest => (a + b) :: rest
  case _ => ls
}

<console>:10: error: type mismatch;
found   : T
required: String
   case a :: b :: rest => (a + b) :: rest

为什么?

【问题讨论】:

    标签: scala types


    【解决方案1】:

    对于任何类型T,操作T + T 没有任何意义。 (所有类型都支持+吗?不。想想添加两条狗或两名员工。)

    在您的情况下,字符串连接运算符被调用(通过any2stringadd pimp 添加),其返回类型(显然)是String。因此出现错误消息。

    您需要一种方法来指定T 类型必须支持您组合两个T 类型的值以产生T 类型的新值的操作. ScalazSemigroup 完全符合要求。

    以下作品:

    def matchList[T : Semigroup](ls: List[T]): List[T] = ls match {
      case 1 :: rest => rest
      case a :: b :: rest => (a |+| b) :: rest // |+| is a generic 'combining' operator
      case _ => ls
    }
    

    【讨论】:

    • 他是否一定希望操作是关联的?
    • 他没有具体说明。而且我想不出一个关联性会伤害他的问题的案例。
    • 你是对的,它不会:matchListcombines 最多两个元素,所以关联性是无关紧要的。 '这只是提醒一下 Semigroup 的规格比T -&gt; T -&gt; T 类型的操作要大得多。 :)
    • 我终于明白那个 Semigroup 到底是什么东西了! :)
    • 使用库(Scalaz)在泛型之间使用+ 是一种开销
    【解决方案2】:

    我认为问题在于(a + b)+ 运算符的唯一通用用法是字符串连接,因此ab 必须都是字符串(或自动转换为字符串)才能做到这一点有效。您的参数化类型 T 不知道是字符串,因此无法编译。

    【讨论】:

    • @confused-demon:在 Scala 中有一个隐含的 any2string 在这种情况下会引发转换。在特定的 Int 情况下不需要隐式转换。
    • @confused-demon 问题在于 Scala 无法知道 T 将成为 Int,因此它无法工作。
    • 对不起,我还没有深入。 any2string implicit 是指if type is unknown in this case it is converted to string 吗?并且,完整地说,如何实现该类型参数化函数以与 Int、Double 和 String 一起使用?
    【解决方案3】:

    在第二个示例中,声明类型为Tab 变量不能转换为String,这是从您的程序推断出的+ 所需的参数类型(即view 应用于+在没有任何其他信息的情况下的参数类型。

    在第一个示例中,推理可以猜测要应用的正确 + 函数,考虑到它将列表元素的类型作为参数,并且幸运的是,您在类型声明中提到了这些元素的类型是Int。尝试输入

    "1"+2
    
    1 + 2
    

    ... 在 REPL 中,看看 Scala 试图做什么。然后阅读views

    现在,我推测通过使用上面的类型参数T,您正在尝试编写一个适用于 any 数字类型的函数,不是吗?在这种情况下,您可以使用 Numeric 特征。在提出以下建议之前,我会让你阅读implicits

    def matchList[T](ls: List[T])(implicit n:Numeric[T]): List[T] = {
      import n.mkNumericOps
      ls match {
        case 1 :: rest => rest
        case a :: b :: rest => (a + b) :: rest
        case _ => ls
    }}
    

    你得到:

    matchList(List(1,2,3))
    res2: List[Int] = List(2, 3)
    matchList(List(2,3,4))
    res4: List[Int] = List(5, 4)
    matchList(List(2.0,3.0,4.0))
    res5: List[Double] = List(5.0, 4.0)
    

    【讨论】:

      【解决方案4】:

      没有任何导入:

      def matchList[T](ls: List[T])(implicit wrapper:Numeric[T]): List[T] = ls match {
        case 1 :: rest => rest
        case a :: b :: rest => wrapper.plus(a, b) :: rest
        case _ => ls
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-09-26
        • 1970-01-01
        • 2022-10-13
        • 2018-12-13
        • 2015-04-03
        • 1970-01-01
        • 1970-01-01
        • 2021-06-14
        相关资源
        最近更新 更多