I was looking at Tuple and I’m trying to understand how to use that.
Looks like a polymorphic function type to me.
If I do (1, “test”, true).map([t] => (x: t) => ???) I can do very generic things, e.g., wrap the values in some type constructor like Option(x)
But it would be great to actually match on the type so I can do something more useful with the element. For example:
(1, “test”, true).map(\[t\] => (x: t) => x match
case s: String => s.toLowerCase
case other => other
)
This ofc. does not compile. I could coerce the type, e.g., x.toLowerCase.asInstanceOf(t), which is nasty.
I guess the type is erased and I can’t really achieve what I want in a type safe way using this?
Is there a better way to achieve what I want?
1 Like
Your two basic choices are to use a typeclass or a match type.
A match type will work if the set of types you need to operate on is closed and known in advance:
scala> type Flip[T] = T match
case String => Int
case Int => String
scala> def flip[T](t: T): Flip[T] = t match
case s: String => s.length
case i: Int => i.toString
def flip[T](t: T): Flip[T]
scala> ("two", 3, "four").map([T] => (t: T) => flip(t))
val res0: (Int, String, Int) = (3, "3", 4)
It’s unfortunate one can’t simply .map(flip), because the language doesn’t currently offer eta-expansion to polymorphic function types, as per Polymorphic function parameter types not inferred · Issue #6892 · scala/scala3 · GitHub
If you want to allow arbitrary types to be added later, then you can do the same thing with a typeclass, declaring an individual typeclass instance for each input type you want to support.
3 Likes
I was not able to make it work with typeclasses:
trait Showable[T]:
extension (x: T)
def show(): String
given Showable[Int] = new {
extension (x: Int)
def show(): String = x.toString
}
given Showable[String] = new {
extension (x: String)
def show(): String = '"' + x + '"'
}
def show[T : Showable as T](x: T): String = x.show()
("two", 3, "four").map([T] => (t: T) => show(t)) // No given instance of type worksheet.Showable[T] was found for parameter T of method show in object worksheet
And I had to fight to get an understandable error message ^^’
Here is my original attempt:
trait Flippable[T]:
type Out
extension (x: T)
def flip(): Out
// Sadly netiher work as 1: the compiler doesn't infer `Out`, and 2: extension methods apparently don't work for SAM types:
// given Flippable[Int] = _.toString
// given Flippable[Int] = (x: Int) => x.toString
given Flippable[Int] = new {
type Out = String
extension (x: Int)
def flip(): Out = x.toString
}
given Flippable[String] = new {
type Out = Int
extension (x: String)
def flip(): Out = x.length
}
def flip[T : Flippable as T](x: T): T.Out = x.flip()
("two", 3, "four").map([T] => (t: T) => flip(t)) // No given instance of type worksheet.Flippable[T] was found for parameter T of method flip in object worksheet
1 Like
Oh interesting, was I too hasty there? I’d like to take a second look this week…