Skip to content

Instantly share code, notes, and snippets.

@adamw
Created June 10, 2022 17:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamw/20724e6e8178318981cc0bd05428a153 to your computer and use it in GitHub Desktop.
Save adamw/20724e6e8178318981cc0bd05428a153 to your computer and use it in GitHub Desktop.
object UsingIO:
trait Connection
trait User
case class IO[-R, +A]():
def *>[R1 <: R, B](that: => IO[R1, B]): IO[R1, B] = IO()
def foo(): IO[Connection, Unit] = IO()
def bar(): IO[User, Unit] = IO()
def explicit(): IO[Connection & User, Unit] = foo() *> bar()
// no compiler error
def inferred() = foo() *> bar()
// Both Scala compiler & IntelliJ properly infer the type
def inferredUsage(): IO[Connection & User, Unit] = inferred()
object UsingContextFN:
trait Connection
trait User
type Transactional[T] = Connection ?=> T
type Secure[T] = User ?=> T
def foo(): Transactional[Unit] = ()
def bar(): Secure[Unit] = ()
def explicit(): Transactional[Secure[Unit]] =
foo()
bar()
// IntelliJ infers the Unit type, Scala compiler reports an error
def inferred() =
foo() // compiler error
bar()
@odersky
Copy link

odersky commented Jun 10, 2022

Good example! Yes, indeed, we need the explicit types here. Not sure what can be done about it. I guess even if inference would work, I would find inferred objectionable since I have no clue what its semantics is. So yes, explicit types are more verbose, but they also help understanding.

@adamw
Copy link
Author

adamw commented Jun 11, 2022

@odersky Explicit types - definitely, as a "best practice" or maybe even a compiler-enforced requirement for public methods (but probably this would be part of sth like wart-remover than of the scala compiler). Still, how do we get these types? Having them inferred by the IDE, or suggested by the compiler is a very common scenario. It's good to have the types but it's much better if we don't have to write them down :) So I'd insist that for a "capability" feature (however implemented), inference is a must-have.

As for this particular implementation - using context functions - maybe you'd need some kind of marker trait specifying that the implicit requirement should propagate during type inference phase? Maybe that's complete nonsense, I'm not that familiar with the inferencing mechanism in Scala, apart from being a user :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment