Tasks and typed Failure

I'd really like to have typed failures on some of my Tasks and be able to chain them accordingly. The lack of an initializer for Failure types other than Never and Error has me typing Tasks as:

Task<Result<Success, Failure>, Never>

and interspersing Result handling in the chain. This seems like it defeats the entire purpose of giving Task the second generic type and I feel like I'm missing something. Any ideas or comments?

The reason the Task has an error type has so far only been future proofing. There’s currently no way to make use of that type indeed (other than Error or Never).

It’s up in their air if or when those would be made use of but it’s correlated to if or when typed throws ~about~ would be a thing β€” at least that was my impression from the reviews while we worked on these.

edit: typo

1 Like

that's largely what I expected. My problem is that I'm particularly obdurate about error handling and would like everything typed. I may experiment with some sort of wrapper type that imposes the Result type for Success and Never for Failure.

Also curious as to the thinking on why map and flatMap didn't get implemented on Task, those seem relatively trivial to implement.

The purpose of async/await is to not have to implement such map operators.

What you know as map operations etc

someValueFuture.map { value in
  make(value) 
}

becomes:

let value = await someValue
let made = make(value)

So it is a non-goal to add map and friends to Task.

They are a reasonable thing on AsyncSequence though, but there again one could often use a for await loop instead.

You can experiment around yeah -- though as you know, any kind of throws won't fit this story because they're effectively always Error. You could force some API that forces returning results yeah; the Task itself would be not erroring thought I expect.

Hope this helps,

What you know as map operations etc

someValueFuture.map { value in
  make(value) 
}

becomes:

let value = await someValue
let made = make(value)

All true and reasonable. I do find that the functional style makes it easier (for me anyway) to compose testable pieces together than does the SSA style that use of the await keyword dictates. So, like Sequence hides for and Result hides throws, I'm finding myself tending to hide usage of await inside of higher order functions, primarily associated with Task. It's a fun exercise to see how much of Haskell I can force into Swift. :)

But I get that that does not align with Apple's goals for the language.

@ktoso Should the value and result properties be in a Task where Failure == Error extension?

https://github.com/apple/swift/pull/38402

(However, typed throws may not be possible, if the runtime can also throw a CancellationError.)