Functions in Scala are modelled via FunctionN
trait. For example, simple one-input-one-output functions are all instances of the following trait:
trait Function1[-T1, +R] extends AnyRef
So what you're asking is "how can I make instances of Function
also become subclasses of C
". This is not doable via standard subtyping / inheritance, because obviously we can't modify the Function1
trait to make it extend your custom class C
. Sure, we could make up a new class to represent the function as you suggested, but that will only take us so far and it's not so easy to implement, not to mention that any function you want to use as C
will have to be converted to your pseudo-function trait first, which will make things horrible.
What we can do, however, is create a typeclass which then contains an implementation for A -> B
, among others.
Let's take the following code as example:
trait A
trait B
trait C[T]
object C {
implicit val fa = new C[A] {}
implicit val fb = new C[B] {}
implicit val fab = new C[Function1[A, B]] {}
}
object Test extends scala.App {
val f: A => B = (a: A) => new B {}
def someMethod[Something: C](s: Something) = {
// uses "s", for example:
println(s)
}
someMethod(f) // Test$$$Lambda$6/1744347043@dfd3711
}
You haven't specified your motivation for making A -> B extend C, but obviously you want to be able to put A, B and A -> B under the "same umbrella" because you have, say, some method (called someMethod
) which takes a C
so with inheritance you can pass it values of type A, B or A -> B.
With a typeclass you achieve the same thing, with some extra advantages, such as e.g. adding D
to the family one day without changing existing code (you would just need to implement an implicit value of type C[D]
somewhere in scope).
So instead of having someMethod
take instances of C
, it simply takes something (let's call it s
) of some type (let's call it Something
), with the constraint that C[Something]
must exist. If you pass something for which an instance of C doesn't exist, you will get an error:
trait NotC
someMethod(new NotC {})
// Error: could not find implicit value for evidence parameter of type C[NotC]
You achieve the same thing - you have a family of C
whose members are A
, B
and A => B
, but you go around subtyping problems.