4 ms·
Indeed, without a type-class constraint on the type constructor this isn't useful at all. Something like the following Scala 3 code is closer to the actual int
by still_grokking 6y ago
Indeed, without a type-class constraint on the type constructor this isn't useful at all.
Something like the following Scala 3 code is closer to the actual intend, I think:
@main def entryPoint =
trait ConsoleLogger[W[_]]:
extension[E] (w: W[E]) def log(): Unit
given ConsoleLogger[List] with
extension[A] (list: List[A]) def log() = println(list)
given ConsoleLogger[Some] with
extension[A] (some: Some[A]) def log() = println(some)
def process[E, L[_] : ConsoleLogger](input: L[E]): Unit =
input.log()
process(List(23))
process(Some("'process' is generic!"))
//process(None) // Does not compile — even Some and None are interchangeable under subtype polymorphism
Here process(input) can work with any wrapped input as long as a ConsoleLogger instance is given for a specific wrapper type. The point is: There doesn't need to be any relation between the wrapper types (like in the example with List and Option.Some), only the "shape" needs to match W[_] (which could be actually also adapted with type lambdas in case it doesn't match, but not going into this here).