mimo
mimo

Reputation: 33

High order function of generic operations

I have the following Enum

sealed trait DataTyp
case class IntN(n: Int) extends DataTyp
case class FltN(n: Float) extends DataTyp
case class StrL(d: String) extends DataTyp
case class Bool(b: Boolean) extends DataTyp

And I want to implement arithmetic, relational and logical operations on them. There is obvious code repetition the could be optimizing when doing this. Instead of doing a ridiculous amount of pattern matching for doing the correct format of operations. Is there a way of doing a generic function that I can pass as a parameter when doing the pattern matching? Given that the only thing that is changing most of the time in pattern matching is the operation function.

I already know that you can do generic arithmetic operations methods with something like this:

  def add[T](x: T, y: T)(implicit num: Numeric[T]): T = {
    import num._
    x + y
  }

But for some reason I can't use type parameters as functions (only on methods). So what can I do?

Upvotes: 3

Views: 385

Answers (1)

OlivierBlanvillain
OlivierBlanvillain

Reputation: 7768

There is not nice syntax for it, but much use the same trick that scala uses for A => B: use a trait.

trait MyGenericOperation {
  def add[T](x: T, y: T)(implicit num: Numeric[T]): T = {
    import num._
    x + y
  }
}

You could also abstract further:

trait GenFunctionTTTWithTC[TC[_]] {
  def apply[T: TC](x: T, y: T): T
}

Note that to convert all the possible higher order signature ([A, B](A, B) => A), [A, B](A, B) => B), [A, B, C](A, B) => C), ...), you would need a large number of trait.

The kind projector plugin implements syntax for a certain kind of polymorphic lambda that correspond to natural transformation. That's probably not going to be useful for your use case, I'm just pointing this out to show that people have considered extending the Scala syntax to simplify abstraction over type parametric functions.

Upvotes: 1

Related Questions