I have a situation where none of the solutions that I'm aware of feel like good ones. I am trying to define a typeclass, like the example below, where it has an abstract type S that must implement another typeclass (not shown) Valid[A]. It feels like the easiest way to do this would be to create an apply constructor, which will force the user to enter S and automatically bring in an implicit instance for sIsValid.
The problem with this is that function changeType takes a type parameter. Despite some googling I have not figured out how to write a type annotation for a function that takes a type parameter (this may be because it seems like Scala does not allow anonymous functions with type parameters). Does my approach here seem like a sensible one? If I can provide a type annotation for changeType then the typeclass user can still pass a non-anonymous function to the apply constructor, which seems like a mostly satisfactory solution.
abstract class IsTC[A[_], T] {
// type S is an abstract type rather than type parameter, but must implement Valid[A]
type S
implicit val sIsValid: Valid[S]
def get(self: A[T], i: Int): T
def changeType[_T]: A[_T]
}
object IsTC {
def apply[A[_], T, _S](
fget: (A[T], Int) => T,
fchangeType: // what should this type annotation be?
): IsTC[A, T] { type S = _S } = new IsTC[A, T] {
type S = _S
def get(self: A[T], i: Int) = fget(self, i)
def changeType[_T]: A[_T] = fchangeType[_T]
}
}
Any help/thoughts gratefully received.
Scala 2 doesn't support polymorphic functions. Polymorphic can be methods, not values. And functions are values. Polymorphic functions can be emulated with wrappers
or
like
shapeless.Poly. They generalize ordinary functionsTry
Dotty has polymorphic functions
[A <: U] => (a: A) => f[A](a)of polymorphic function types[A <: U] => A => B[A]but there isimplementation restriction: polymorphic function types must have a value parameterso you can't have polymorphic function type[X] => A[X](not to be confused with a type lambda[X] =>> A[X]) currently even there.Also (besides emulation with wrappers) some polymorphic types can be expressed via existential types:
[A] => B[A] => C(for constantC) is actuallyB[_] => C.This is because
∀a: (B(a) => C)≡(∃a: B(a)) => C.