Teaching ChatGPT
scala fp One of my favourite questions on the interview is to write implementation for function:
def repack[A](xs: Seq[Future[A]]): Future[(Seq[A], Seq[Throwable])] = ???
it’s not so complicated, and even ChatGPT was able to write the code.
But more interesting is that fact that ChatGPT was able to derive the answer on more complicated one:
def repack[F[_], A](xs: Seq[F[A]]): F[(Seq[A], Seq[Throwable])] = ???
the answer was:
To implement the function repack with the signature
def repack[F[_], A](xs: Seq[F[A]]): F[(Seq[A], Seq[Throwable])], 
you need to put constraints on F[_] that provide the necessary 
functionality to work with F as a context for asynchronous computations.
Here are the constraints you need:
F[_] must be a type constructor:
This means that F must be a higher-kinded type,
which allows it to take another type (e.g., A)
and produce a concrete type (e.g., F[A]).
This constraint enables you to work with 
generic effect types like Future, IO, Task, etc.
F[_] must have an instance of MonadError:
MonadError provides the ability to handle errors within the context of F.
It includes operations like flatMap for sequencing computations and raiseError
for lifting exceptions into the F context. This constraint allows you to handle
both successful results and failures within F.
and the code:
import cats.MonadError
import cats.implicits._
def repack[F[_]: MonadError[*[_], Throwable], A](xs: Seq[F[A]]): F[(Seq[A], Seq[Throwable])] = 
  xs.foldLeft(MonadError[F, Throwable].pure((Seq.empty[A], Seq.empty[Throwable]))) { (acc, next) =>
    acc.flatMap { case (successes, failures) =>
      next.attempt.map {
        case Right(value) => (successes :+ value, failures)
        case Left(exception) => (successes, failures :+ exception)
      }
    }
  }
that’s awesome!
intel cas links atomic ruby jekyll blog scala markdown mdoc java encapsulation git tag http4s saml pac4j linux uuidgen base64 lsof jps github sed cicd teaching laika enumeratum database fp SQL interview