Aarkon
Aarkon

Reputation: 488

Scala syntax for polymorphism in val functions

This is potentially super easy, but I can't find any documentation on my problem.
There are two ways to define a functions in Scala, one with the def and the other with the val keyword. As an adept in functional programming, I'd like to use the latter more.

Now I have a problem: It's no problem to write a def function with a polymorphic type parameter:

def function[T](n: T) = {print(n)} // syntactically fine

How to do the same thing with the val keyword still eludes me though. This naive approach is syntactically invalid:

val function[T]: (a: T) => print(a) // Doesn't compile

That said, it is absolutely possible that I misunderstand Scala's approach on polymorphism and generics here.

Upvotes: 1

Views: 167

Answers (2)

Mateusz Kubuszok
Mateusz Kubuszok

Reputation: 27535

In Scala 2 it is impossible to define parametric function, only method.

In Scala 3 polymorphic function type is introduced:

val fun: [A] => A => Unit = [A] => a => println(a.toString)

Workaround used in 2 by Cats and friends were traits with polymorphic apply

trait MySpecialFunctionlikeThing {
  def apply[A](a: A): Unit
}

Unfortunately, single abstract method (SAM) doesn't work with things like that, so some tricks were used to make it easy to lift function into such methods:

object MySpecialFunctionlikeThing {

  type Arbitrary

  def lift(f: Arbitrary => Unit): MySpecialFunctionlikeThing =
    new MySpecialFunctionlikeThing {
      def apply[A](a: A): Unit = f(a.asInstanceOf[Arbitrary])
    }
}

val fun = MySpecialFunctionlikeThing.lift(a => println(a))

The latter I saw in several different forms: the above, one using existential types and one using one of the above for method signature and macro for implementation (see FunctionK.lift).

Quite often, though, you can get away with what you used that is parametric, nullary method returning non-parametric function.

def fun[A]: A => Unit = a => println(a)

Upvotes: 6

Matthias Berndt
Matthias Berndt

Reputation: 4577

This would require higher-rank types, which isn't supported in Scala 2.

It is supported in Scala 3: https://dotty.epfl.ch/docs/reference/new-types/polymorphic-function-types.html

Upvotes: 1

Related Questions