I came across to this to functions, which implements Traverse for Functor and functions to Option/Either using new boundary capability:
def traverseToOption[F[_], A, B](fa: F[A])(f: A => Option[B])(using functor: Functor[F]): Option[F[B]] =
boundary:
Some(functor.map(fa)(
f(_) match
case Some(value) => value
case None => break(None)
))
def traverseToEither[F[_], A, B](fa: F[A])(f: A => Either[_, B])(using functor: Functor[F]): Either[_, F[B]] =
boundary:
Right(functor.map(fa)(
f(_) match
case Right(value) => value
case Left(error) => break(Left(error))
))
I tested them like this:
case class Box[A](a: A)
given Functor[Box] with
def map[A, B](fa: Box[A])(f: A => B): Box[B] = Box(f(fa.a))
traverseToOption(Box("123"))(_.toIntOption) // Some(Box(123))
traverseToEither(Box("123"))(_.toIntOption.toRight("Error")) // Right(Box(123))
traverseToOption(Box("abc"))(_.toIntOption) // None
traverseToEither(Box("abc"))(_.toIntOption.toRight("Error")) // Left(Error)
And results are correct. So, is this implementation generally correct? Can it be generalized to types other than Option and Either?