Problems inferring correct type for extension methods
See original GitHub issueCompiler version
3.0.0-RC1
Minimized code
object Minimized extends App {
trait Monad[F[_]]:
def pure[A](a: A): F[A]
extension[A,B](fa :F[A])
def map(f: A => B): F[B] = fa.flatMap(a => pure(f(a)))
def flatMap(f :A=>F[B]):F[B]
end Monad
// Instances of monad
// note that if you comment out eitherMonad the code will compile, even though the Either type is never used
given eitherMonad[Err]: Monad[[X] =>> Either[Err,X]] with
def pure[A](a: A): Either[Err, A] = Right(a)
extension [A,B](x: Either[Err,A]) def flatMap(f: A => Either[Err, B]) = {
x match {
case Right(a) => f(a)
case Left(err) => Left(err)
}
}
given optionMonad: Monad[Option] with
def pure[A](a: A) = Some(a)
extension[A,B](fa: Option[A])
def flatMap(f: A => Option[B]) = {
fa match {
case Some(a) =>
f(a)
case None =>
None
}
}
case class Transformer[F[_]: Monad,A](val wrapped: F[A])
given transformerMonad[F[_]: Monad]: Monad[[X] =>> Transformer[F,X]] with {
def pure[A](a: A): Transformer[F,A] = Transformer(summon[Monad[F]].pure(a))
extension [A,B](fa: Transformer[F,A])
def flatMap(f: A => Transformer[F,B]) = {
val ffa: F[B] = summon[Monad[F]].flatMap(fa.wrapped)(a => f(a).wrapped)
Transformer(ffa)
}
}
type TransformerOption[A] = Transformer[Option, A]
val pure10 = summon[Monad[TransformerOption]].pure(10)
val fm = pure10.flatMap(a => Transformer(Option(a + 1))) // COMPILE ERROR HERE
println(fm)
}
Output
Minimized.scala:49:19
value flatMap is not a member of Minimized.Transformer[Option, Int].
An extension method was tried, but could not be fully constructed:
Minimized.transformerMonad[F](
/* ambiguous: both given instance eitherMonad in object Minimized and object optionMonad in object Minimized match type Minimized.Monad[F] */
summon[Minimized.Monad[F]]
).flatMap()
val fm = pure10.flatMap(a => Transformer(Option(a + 1)))
Expectation
Code should compile with no ambiguity
Issue Analytics
- State:
- Created 3 years ago
- Comments:6 (1 by maintainers)
Top Results From Across the Web
VS Code incorrectly infers types from extension methods
Specifying the type explicitly works, but that's rather a lot of typing, and this should be simple enough. It looks to me like...
Read more >Type inference in extension methods #6275 - GitHub
I'd like to add an extension method that has a type parameter with a constraint as well that also relies on other type...
Read more >Extension methods and Generics (Extension Methods Part 5)
Attempting to resolve all types in one pass, the compiler would infer two conflicting types for T3, one from parameter X and another...
Read more >Why I Don't Like C# Extension Methods - DaedTech
You can make it look as though GetWordCount() is a method of string, even though it isn't. This means that, done right, you...
Read more >Extension methods - Dart
Extension methods do work with Dart's type inference. The following code is fine because the variable v is inferred to have type String...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Here
expands to
and at this point compiler is confused while at the point of evaluating
transformerMonad
bothtransformerMonad[Option]
andtransformerMonad[Either]
make sense (the compiler doesn’t know yet that you’re in the context ofOption
rather thanEither
) so it’s not clear which implicit should be taken. You can try adding some kind of extension proxy to make this to make your snippet compileThanks for the help, so it seems like this isn’t a bug and can be closed.