Suma
Suma

Reputation: 34413

Can function type be defined by inference?

Scala type inference is really nice and it is easy to get used not to have to write things twice. The more it hurts when you have to. One such example are function types.

Sometimes I would like to create a named type for some function signature. Is it possible somehow? Is there some way to get the compile-time type of the function so that I do not have to type it again when defining FType?

object Foo {
  def f(a:Int, b:Int, x:Double, y:Double, name:String) : Unit = {}

  //type FType = typeOf(f) // can compiler provide me a compile time type somehow?
  type FType = (Int,Int,Double,Double,String) => Unit

  def callF( func:FType) = func(0,0,0,0,"")
}

Is there something like C++ decltype in Scala which could be used for this purpose?

Upvotes: 2

Views: 132

Answers (1)

blouerat
blouerat

Reputation: 692

I'm not quite sure what you're trying to achieve here, if I understand correctly you want to avoid typing (a:Int, b:Int, x:Double, y:Double, name:String) two times.

What about defining FType yourself upfront and then simply reusing it in f and callF?

object Foo {
  type FType = (Int,Int,Double,Double,String) => Unit

  def f: FType = (a, b, x, y, name) => ()

  def callF(func: FType) = func(0,0,0,0,"")
}

If you actually want to abstract over FType, it's a significantly different problem, but it doesn't seem to be the case as you're forcing the type by calling func(0,0,0,0,"").

You don't have decltype in Scala because types are not first class citizens like they can be in Idris for example. That said, you should be able to write it using Shapeless and/or macros.

If you want to fix the types and the arguments and reuse them, the simplest solution is to turn them into a case class. You can then use import to access your fields directly:

object Foo {
  case class FArgs(a: Int, b: Int, x: Double, y: Double, name: String)

  def f(args: FArgs): Unit = {
    import args._
    println(name) // or whatever you want to do
  }

  def callF(func: FArgs => Unit) = func(FArgs(0,0,0,0,""))
}

Upvotes: 2

Related Questions