def flatMap[B](f: A => IO[B]): IO[B] = new:
def unsafeRun = f(self.unsafeRun).unsafeRun
This method creates a new IO object
I don't understand the use of new without a type. Feels like structural type, but not quite sure. I'm Just starting to transition to scala 3.
What you described is a new feature of Scala 3, which allows you to drop type name when creating an anonymous instance of some class if the type can be inferred:
trait Foo {
def a(i: Int): String
}
// this is what Scala 2 requires
val foo1: Foo = new Foo {
def a(i: Int): String = i.toString
}
// this is what Scala 3 allows
val foo2: Foo = new { // Foo in inferred from value foo2 type
def a(i: Int): String = i.toString
}
// this is Scala 3 with braceless syntax
val foo3: Foo = new:
def a(i: Int): String = i.toString
While it feels like a structural typing it's a nominal typing with type inference extended to anonymous classes created with new
keyword.
You could even use this in some nested contexts like:
trait Foo:
def a(i: Int): String
trait Bar:
def foo: Foo
trait Baz:
def bar: Bar
val baz: Baz = new:
def bar = new:
def foo = new:
def a(i: Int): String = i.toString
but it becomes unreadable almost immediately, which is why this presentation classifies it as an Scala-3-specific antipattern.
It might be a really nice way to quickly to hack some one-time-use script, but please avoid using it in larger long-living codebases.