简体   繁体   中英

Scala: Default value for function parameter with generics

I am having trouble for setting a default value for a function parameter when the types are generics.

My function signature looks like:

  def doStuff[ K, T ]( result: Future[ Seq[ T ] ] )
                     ( transform: T => Option[ K ] ): Future[ Either[ String, Option[ K ] ] ] = {
  }

And I am aware that I cat set a default value to a function parameter like:

  def doStuff(a: Int)
             (f: Int => Option[Int] = k => Option(k)): Future[ Either[ String, Option[ Int ] ] ] = {
  }

However I can't combine these generic types with a default function value

  def doStuff[ K, T ]( result: Future[ Seq[ T ] ] )
                     ( transform: T => Option[ K ] = k => Option(k)): Future[ Either[ String, Option[ K ] ] ] = {
  }

with an obvious error message: Option[T] does not conform expected Option[K]

my last resort is to pass class tag in for K and T and change the default parameter from k => Option(k) to

def doStuff[ K: ClassTag, T ]( result: Future[ Seq[ T ] ] )
                               ( transform: T => Option[ K ] = {
                                 case m: K => Option( m )
                                 case _ => None
                               } ): Future[ Either[ String, Option[ K ] ] ] = {
  }

but this approach will force me to pass in my generic parameters on function call.

Can anyone see any other approach?

I haven't achieved it with the signature you provided with two parameter lists. But I wonder if you can use it with one parameter list:

def toOption[R](x: R): Option[R] = Option(x)

def doStuff[K, T](result: Future[Seq[T]], transform: T => Option[K] = toOption[K] _): Future[Either[String, Option[K]]] = {
  result.map(r => Right[String, Option[K]](transform(r.head)))
}

// Then, if you need a function of the second parameter, you can use partially applied function:
val rf: (Int => Option[Int]) => Future[Either[String, Option[Int]]] = doStuff[Int, Int](Future(List(1, 2)), _)

// Or call with default argument:
val r: Future[Either[String, Option[Int]]] = doStuff[Int, Int](Future(List(1, 2)))

// These lines should print the same
println(rf(toOption))
println(r)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM