312748 (4) [Avatar] Offline
In exercise 6.2, we are asked to implement AccountService using Task instead of Future. The hint mentions that you don't need monad transformers but I can't seem to figure out how to achieve this.

For example, if we modify our Valid[A] type to the following:

type Valid[A] = Task[NonEmptyList[String] \/ A]
type AccountOperation[A] = Kleisli[Valid, AccountRepository, A]

Then the methods in our service class will return tasks of type Task[NonEmptyList[String] \/ A] and in order to work with these values without executing them, we still have to resort to a nested for-yield. Well, either that or implement a monadic transformer like with the Future example.

The other alternative that I was thinking was to implement the Valid type as:

type Valid[A] = Task[A]

and then return all of our errors as exceptions within the Task:

Task {
  repo.query(no) match {
    case \/-(x) => x
    case -\/(errors) => throw new Exception(errors.mkString(","))

This, however, did not seem very functional as it relies on exceptions. Am I missing something? Is our implementation really simpler when we use Task instead of Future?