Learning Scala 3.
below code
// monad defined for Option
given Monad3[Option] with {
def flatMap_[A, B](ma: Option[A])(fm: A => Option[B]): Option[B] = ???
def return_[A](a: A): Option[A] = ???
}
extension[M[_] : Monad3, A] (cont: M[A])(using monad: Monad3[M]) {
def flatMap_[B](f: A => M[B]): M[B] = monad.flatMap_(cont)(f)
}
extension[M[_] : Monad3, A] (contCont: M[M[A]])(using monad: Monad3[M]) {
def join_(): M[A] = monad.join(contCont)
}
// test
val flattenedOpt = Option(Option("hello!")).join_()
println(flattenedOpt)
works for me.
Question: how do I modify signature of the helper extension for join so the below code with subtypes also works? Question is about Scala 3 syntax, not about monads, libraries, etc...
val flattenedOpt = Some(Some("hello!")).join_()
Is it smth with type bounds?
thanks
Question is about Scala 3 syntax, not about monads, libraries, etc...
Well, the thing is that the question is exactly about monads, not Scala 3 syntax etc. You can define separate instances of Monad
for Option
and Some
given Monad3[Option] with
def flatMap_[A, B](ma: Option[A])(fm: A => Option[B]): Option[B] = ma match
case Some(a) => fm(a)
case None => None
def return_[A](a: A): Option[A] = Some(a)
given Monad3[Some] with
def flatMap_[A, B](ma: Some[A])(fm: A => Some[B]): Some[B] = fm(ma.value)
def return_[A](a: A): Some[A] = Some(a)
But generally you can't derive an instance for subtype or supertype from an instance for a type. That's because Monad
can be only invariant with respect to M[_]
, not covariant (Monad[+M[_]]
) or contravariant (Monad[-M[_]]
).
Calling generic function with Functor using subclass (cats/scalaz)
Why can find `Functor` instance for Tree but not for Branch or Leaf?
Cats instances for Some and None et al
Can I get the compiler to realize there is an Applicative for the superclass?
Also for some ADTs / GADTs (case classes, sealed-trait hierarchies) parametrized with a type constructor, generic derivation is possible for the type classes Functor
, Traversable
, Foldable
but not for Monad
or Applicative
because there is no standard way to flatten arbitrary data types.
Why there is no way to derive Applicative Functors in Haskell?
Why is there no `-XDeriveApplicative` extension?
Haskell - Automatic Monad instance
If you're really asking just about Scala 3 syntax for type bounds, it's the same as in Scala 2 i.e. def foo[A <: B : TC]
(for a type class TC[A]
), def foo[A[x] <: B[x] : TC]
(for a type class TC[A[_]]
).
You shouldn't write extension[M[_]: Monad3, A](cont: M[A])(using monad: Monad3[M])
. It should be either implicit parameter extension[M[_], A](cont: M[A])(using monad: Monad3[M])
or context bound extension[M[_]: Monad3, A](cont: M[A])
.