class OptionT[F[_]: Monad, A](value: F[Option[A]]) { def flatMap[B](f: A => OptionT[F, B]): OptionT[F, B] = OptionT(value.flatMap(ga => ga.traverse(f.andThen(_.value)).map(_.flatten))) } object OptionT { def pure[F[_]: Monad](a: A): OptionT[F, A] = new OptionT(F.pure(Some(a))) }