Scala 隐式类必须有一个主构造函数,在第一个参数列表中只有一个参数

Posted

技术标签:

【中文标题】Scala 隐式类必须有一个主构造函数,在第一个参数列表中只有一个参数【英文标题】:Scala implicit class must have a primary constructor with exactly one argument in first parameter list 【发布时间】:2021-10-16 13:44:47 【问题描述】:

大家好,我有这样的问题:

  implicit class mapValue[T](f: Future[T])
    def mapValue[T]( f: Future[T] )(implicit ec: ExecutionContext): Future[Try[T]] = 
      val prom = Promise[Try[T]]()
      f onComplete prom.success
      prom.future
    
  
  

  implicit class traverseFilteringErrors[A, B](seq: Seq[A])(f: A => Future[B])  // >*It says implicit class must have a primary constructor with exactly one argument in first parameter list here 
    def traverseFilteringErrors[A, B](seq: Seq[A])(f: A => Future[B])(implicit ec: ExecutionContext): Future[Seq[B]] = 
      Future.traverse( seq )( f andThen mapValue ) map ( _ collect case Success( x )  => x  )  // >and Type mismatch. Required: Future[B] => NotInferredA, found: Future[Nothing] => mapValue[Nothing] here.
    

  

上面写着:

隐式类必须有一个主构造函数,在 def traverseFilteringErrors 的第一个参数列表中只有一个参数

类型不匹配。必需:Future[B] => NotInferredA,找到:Future[Nothing] => mapValue[Nothing] at f and Then mapValue part

我是 scala 的新手,我应该怎么做才能解决这个问题?

【问题讨论】:

什么问题?请解释发生了什么问题。添加相应的错误信息。 @talex 已编辑。 首先从def mapValue[T]( f: Future[T] ) 中移除类型参数——它会覆盖第一类。我也认为这种方法应该是无参数的。在过滤错误方面 - 我想说还有更多 convenient 方式 【参考方案1】:

您似乎正在尝试创建一些扩展方法,但您对语法的工作原理有点困惑。

这个想法是implicit class 将只有一个参数,即您要添加扩展方法的值。但是,您在扩展方法的参数中再次复制该值,这是没有意义的。 您还有其他语法问题,例如遮蔽泛型参数。

在修复该问题并使用最佳实践(例如使您的implicit classes 也成为值类)之后,我们有几个可以轻松修复的语法错误。

最终结果是这样的:

import scala.concurrent.ExecutionContext, Future, Promise
import scala.util.Try, Success

object syntax 
  implicit class mapValue[T](private val f: Future[T]) extends AnyVal 
    def mapValue(implicit ec: ExecutionContext): Future[Try[T]] = 
      val prom = Promise[Try[T]]()
      f.onComplete(prom.success)
      prom.future
    
  

  implicit class traverseFilteringErrors[A](private val seq: Seq[A]) extends AnyVal 
    def traverseFilteringErrors[B](f: A => Future[B])(implicit ec: ExecutionContext): Future[Seq[B]] = 
      Future
        .traverse(seq)(f.andThen(_.mapValue))
        .map(_.collect  case Success( x )  => x )
    
  

一般来说,你似乎对这门语言有点陌生,并且在没有先了解基础的情况下尝试一些高级的东西;无论如何,希望这会有所帮助。


可以看到运行here的代码

【讨论】:

不相关,但您能解释一下为什么将隐式类作为值类是最佳做法吗? @GaëlJ 如果它不是AnyVal,编译器将实例化一个无用的包装类以调用扩展方法(注意这种实例化可能会在运行时进行优化) . - 将其设为 值类 确保它不会被实例化,因为 a.foo(x) 应该像 foo(x, a) 一样被取消 - 请注意 Scala 3中的新 extension 语法> 解决了这个问题,还允许您内联扩展方法以避免额外的调用,这对于 typeclasses 非常有用,因为通常将 4 层间接减少到只有一个打电话。

以上是关于Scala 隐式类必须有一个主构造函数,在第一个参数列表中只有一个参数的主要内容,如果未能解决你的问题,请参考以下文章

Scala中的隐式转换|理解

如何在 Java 中使用 Scala 隐式类

如何在 Java 中使用 Scala 隐式类

Scala 中的隐式类

通过构造函数隐式类类型转换创建的临时对象啥时候被销毁

在 Scala 中为我们的类创建隐式类是个好主意吗[关闭]