Search code examples
scalascala-3

Strange scala 3 syntax - new without type


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.


Solution

  • 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.