1

Hello everyone I have a problem like that:

  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.
    }

  }

It says:

implicit class must have a primary constructor with exactly one argument in first parameter list at def traverseFilteringErrors

and

Type mismatch. Required: Future[B] => NotInferredA, found: Future[Nothing] => mapValue[Nothing] at f and Then mapValue part

I'm new to scala so what should I do to fix the problem?

Guru Stron
  • 102,774
  • 10
  • 95
  • 132
  • 1
    What problem? Please explain what is going wrong. Add corresponding error messages. – talex Aug 13 '21 at 09:52
  • @talex editted. – Hakan Apohan Aug 13 '21 at 10:04
  • 1
    First of all remove type parameter from `def mapValue[T]( f: Future[T] )` - it overwrites the class one. Also i think this method should be parameterless. In terms of filtering out errors - I would say that there are more [convenient](https://stackoverflow.com/questions/20874186/scala-listfuture-to-futurelist-disregarding-failed-futures) ways – Guru Stron Aug 13 '21 at 10:41

1 Answers1

3

It seems you are trying to create some extension methods but you are a bit confused about how the syntax works.

The idea is that the implicit class will have only one parameter, the value on which you are adding the extension methods. But, you are replicating that value again in the arguments of your extension method which doesn't make sense.
You also have other syntax problems like shadowing generic parameters.

After fixing that and using best practices like making your implicit classes also value classes, then we have a couple of syntax errors that can be easily fixed.

The end result is this:

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 })
    }
  }
}

In general, it seems you are bit new to the language and are trying some advanced stuff without understanding first the basis; anyways, hope this helps.


You can see the code running here.

  • Not related but can you explain why it's best practice to have implict class as value class? – Gaël J Aug 13 '21 at 17:00
  • 1
    @GaëlJ without it being an `AnyVal` the compiler will instantiate a useless wrapper class in order to call the extension method _(note such instantiation may be optimized anyways in runtime)_. - Making it a **value class** ensures it won't be instantiated as such `a.foo(x)` should be desugared as just `foo(x, a)` - Note the new `extension` syntax in **Scala 3** solves this problem and also allows you to inline the extension methods to avoid an additional call, which is very useful for **typeclasses** where it was common to have even 4 layers of indirection to be reduced to just a single call. – Luis Miguel Mejía Suárez Aug 13 '21 at 17:56