简体   繁体   中英

Type class with default type parameter

I am trying to solve the expression problem using type classes. I based my work on the example found in a late book of 2013 Scala in Action .

object StuffingSystem {

    trait Stuffer[V, M, P] { def stuff(v: V, m: M, additionalparameters: List[P]): ... }

    case class Input(v: BigDecimal) {

        def stuff[M, P](m: M, additionalparameters: List[P])(implicit stuffer: Stuffer[Input, M, P]) = stuffer.stuff(v, m, additionalparameters)
    }
    case class Material(o: String)
}

object Stuffers {

import StuffingSystem._

implicit object InputStuffer extends Stuffer[Input, Material, Int] {

  def stuff(v: Input, m: Material, p: List[Int]) = {

    ...
  }
}

val stuffed = Input(BigDecimal(101.0)).stuff(Material("o"), List())

The fact is that my stuff() function could use some additional parameters with other Stuffer s. The result I'm trying to get is not to be forced to give an empty parameter when none is required as shown in the example above ; I'd like to be able to write:

val stuffed = Input(BigDecimal(101.0)).stuff(Material(""))
val stuffedWithSomething = Input(BigDecimal(101.0)).stuff(Material(""), List("a", "b"))

I'm looking for an elegant way to do this. I don't quite understand currying but feel like it'd part of the solution.

Is it possible to have default type parameter here? Or is there a better path?

You can use default parameter

  object StuffingSystem {

    trait Stuffer[V, M, P] {
      def stuff(v: V, m: M, additionalparameters: List[P]): Unit
    }

    object Stuffer {
      implicit def mkStuffer: Stuffer[Input, Material, String] = new Stuffer[Input, Material, String] {
        override def stuff(v: Input, m: Material, additionalparameters: List[String]): Unit = ???
      }
    }

    case class Input(v: BigDecimal) {

      def stuff[M, P](m: M, additionalparameters: List[P] = List())(implicit stuffer: Stuffer[Input, M, P]) =
        stuffer.stuff(Input(v), m, additionalparameters)

    }

    case class Material(o: String)

  }

  object Stuffers {

    import StuffingSystem._

    implicit object InputStuffer extends Stuffer[Input, Material, Int] {
      def stuff(v: Input, m: Material, p: List[Int]) = ???
    }

    val stuffed = Input(BigDecimal(101.0)).stuff(Material("o"), List())

    val stuffed1 = Input(BigDecimal(101.0)).stuff(Material(""))
    val stuffedWithSomething = Input(BigDecimal(101.0)).stuff(Material(""), List("a", "b"))
  }

or varargs

  object StuffingSystem {

    trait Stuffer[V, M, P] {
      def stuff(v: V, m: M, additionalparameters: P*): Unit
    }

    object Stuffer {
      implicit def mkStuffer: Stuffer[Input, Material, String] = new Stuffer[Input, Material, String] {
        override def stuff(v: Input, m: Material, additionalparameters: String*): Unit = ???
      }
    }

    case class Input(v: BigDecimal) {    
      def stuff[M, P](m: M, additionalparameters: P*)(implicit stuffer: Stuffer[Input, M, P]) =
        stuffer.stuff(Input(v), m, additionalparameters:_*)
    }

    case class Material(o: String)
  }

  object Stuffers {

    import StuffingSystem._

    implicit object InputStuffer extends Stuffer[Input, Material, Int] {
      def stuff(v: Input, m: Material, additionalparameters: Int*): Unit = ???
    }

    val stuffed = Input(BigDecimal(101.0)).stuff(Material("o"), Seq():_*)

    val stuffed1 = Input(BigDecimal(101.0)).stuff(Material(""))
    val stuffedWithSomething = Input(BigDecimal(101.0)).stuff(Material(""), Seq("a", "b"):_*)
    val stuffedWithSomething1 = Input(BigDecimal(101.0)).stuff(Material(""), "a", "b")
  }

For this you don't need default type parameters, just a normal default parameter:

def stuff[M, P](m: M, additionalparameters: List[P] = Nil)(implicit stuffer: Stuffer[Input, M, P]) = ...

Of course there is a problem if you have multiple Stuffer s with different P , but there already is in your original situation.

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