fun <B, C> parZip(fb: Resource<B>, f: suspend (A, B) -> C): Resource<C>

fun <B, C> parZip(    ctx: CoroutineContext = Dispatchers.Default,     fb: Resource<B>,     f: suspend (A, B) -> C): Resource<C>

Composes two Resources together by zipping them in parallel, by running both their acquire handlers in parallel, and both release handlers in parallel.

Useful in the case that starting a resource takes considerable computing resources or time.

import arrow.fx.coroutines.*
import kotlinx.coroutines.delay

class UserProcessor {
suspend fun start(): Unit { delay(750); println("Creating UserProcessor") }
fun shutdown(): Unit = println("Shutting down UserProcessor")
fun process(ds: DataSource): List<String> =
ds.users().map { "Processed $it" }

class DataSource {
suspend fun connect(): Unit { delay(1000); println("Connecting dataSource") }
fun users(): List<String> = listOf("User-1", "User-2", "User-3")
fun close(): Unit = println("Closed dataSource")

class Service(val db: DataSource, val userProcessor: UserProcessor) {
suspend fun processData(): List<String> = userProcessor.process(db)

val userProcessor = resource {
UserProcessor().also { it.start() }
} release UserProcessor::shutdown

val dataSource = resource {
DataSource().also { it.connect() }
} release DataSource::close

suspend fun main(): Unit {
userProcessor.parZip(dataSource) { userProcessor, ds ->
Service(ds, userProcessor)
}.use { service -> service.processData() }