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
Well, the thing is that the question is exactly about monads, not Scala 3 syntax etc. You can define separate instances of
MonadforOptionandSomeBut generally you can't derive an instance for subtype or supertype from an instance for a type. That's because
Monadcan be only invariant with respect toM[_], 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,Foldablebut not forMonadorApplicativebecause 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 classTC[A]),def foo[A[x] <: B[x] : TC](for a type classTC[A[_]]).You shouldn't write
extension[M[_]: Monad3, A](cont: M[A])(using monad: Monad3[M]). It should be either implicit parameterextension[M[_], A](cont: M[A])(using monad: Monad3[M])or context boundextension[M[_]: Monad3, A](cont: M[A]).