Closed
Description
Compiler version
3.0.0-RC2
Minimized code
object Structures:
trait Functor[F[_]]:
extension [A](fa: F[A])
def map[B](f: A => B): F[B]
def as[B](b: B): F[B] = map(_ => b)
def void: F[Unit] = as(())
trait Applicative[F[_]] extends Functor[F]:
def pure[A](a: A): F[A]
def unit: F[Unit] = pure(())
extension[A](fa: F[A])
def map2[B, C](fb: F[B], f: (A, B) => C): F[C]
def map[B](f: A => B): F[B] =
fa.map2(unit, (a, _) => f(a))
trait Monad[F[_]] extends Applicative[F]:
extension[A](fa: F[A])
def flatMap[B](f: A => F[B]): F[B]
override def map[B](f: A => B): F[B] =
flatMap(a => pure(f(a)))
def map2[B, C](fb: F[B], f: (A, B) => C): F[C] =
flatMap(a => fb.map(b => f(a, b)))
given Monad[List] with
def pure[A](a: A) = List(a)
extension[A](fa: List[A])
def flatMap[B](f: A => List[B]) = fa.flatMap(f)
given Monad[Option] with
def pure[A](a: A) = Some(a)
extension[A](fa: Option[A])
def flatMap[B](f: A => Option[B]) = fa.flatMap(f)
opaque type Kleisli[F[_], A, B] = A => F[B]
extension [F[_], A, B](k: Kleisli[F, A, B])
def apply(a: A): F[B] = k(a)
object Kleisli:
def apply[F[_], A, B](f: A => F[B]): Kleisli[F, A, B] = f
given [F[_], A](using F: Monad[F]): Monad[[B] =>> Kleisli[F, A, B]] with
def pure[B](b: B) = Kleisli(_ => F.pure(b))
extension[B](k: Kleisli[F, A, B])
def flatMap[C](f: B => Kleisli[F, A, C]) =
a => k(a).flatMap(b => f(b)(a))
end Structures
@main def run =
import Structures.{*, given}
println(List(1, 2, 3).map2(List(4, 5, 6), (_, _)))
val p: Kleisli[Option, Int, Int] = Kleisli((x: Int) => if x % 2 == 0 then Some(x) else None)
val q: Kleisli[Option, Int, Int] = summon[Applicative[[B] =>> Kleisli[Option, Int, B]]].pure(20)
println(p.map2(q, _ + _)(42))
Output
value map2 is not a member of Structures.Kleisli[Option, Int, Int].
An extension method was tried, but could not be fully constructed:
Structures.given_Monad_Kleisli[F, A](
/* ambiguous: both object given_Monad_List in object Structures and object given_Monad_Option in object Structures match type Structures.Monad[F] */
summon[Structures.Monad[F]]
).map2()
Expectation
Because p
had type Kleisli[Option, Int, Int]
, scalac should infer F = Option
in given_Monad_Kleisli
and unambiguously select given_Monad_Option
.
This may be a duplicate (e.g. #7999 or similar) but not clear to me. Also not clear if title is correct or misleading.