arrow-kt / arrow-website

This is the main website for Arrow, the functional companion to Kotlin's Standard Library
https://arrow-kt.io
Apache License 2.0
11 stars 22 forks source link

Add some words about Compose #252

Closed serras closed 7 months ago

serras commented 10 months ago

This section makes it more visible that Arrow is a great companion for Compose, and helps combat the impression that Arrow may be "backend-oriented".

serras commented 10 months ago

Looks great!, thanks @serras , Are there any patterns where Raise is useful with compose for error / success display? Perhaps we can include something there too.

I've tried to think about an example, but I couldn't find a good one for this case, as opposed to something like a circuit breaker or optics. Do you have any in mind?

raulraja commented 10 months ago

Looks great!, thanks @serras , Are there any patterns where Raise is useful with compose for error / success display? Perhaps we can include something there too.

I've tried to think about an example, but I couldn't find a good one for this case, as opposed to something like a circuit breaker or optics. Do you have any in mind?

I was thinking about something like:

import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import arrow.core.raise.Raise
import arrow.core.raise.either
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

// Error types
sealed class ErrorType
object UserNotFound : ErrorType()
object NetworkError : ErrorType()

// Data class for User Profile
data class UserProfile(val id: String, val name: String)

// Sample function to fetch user profile
suspend fun Raise<ErrorType>.fetchUserProfile(userId: String): UserProfile {
  delay(3000)
  // Here, you would implement actual logic to fetch the user profile
  // For demonstration, let's assume the user is not found
  raise(UserNotFound)
}

// Main Composable Function
@Composable
fun UserProfileScreen() {
  val coroutineScope = rememberCoroutineScope()
  var userProfile by remember { mutableStateOf<UserProfile?>(null) }
  var error by remember { mutableStateOf<ErrorType?>(null) }

  // Simulate fetch user profile
  coroutineScope.launch {
    either {
      fetchUserProfile("123")
    }.fold(
      ifLeft = { errorType ->
        error = errorType
      },
      ifRight = { profile ->
        userProfile = profile
      }
    )
  }

  when {
    userProfile != null -> Text("User: ${userProfile!!.name}")
    error is UserNotFound -> Text("User not found")
    error is NetworkError -> Text("Network error. Please try again.")
    else -> Text("Loading...")
  }
}

@Composable
@Preview
fun App() {
  MaterialTheme {
    UserProfileScreen()
  }
}

fun main() = application {
  Window(onCloseRequest = ::exitApplication) {
    App()
  }
}

But I don't know if this is considered a good pattern in Compose.

serras commented 10 months ago

@raulraja I've added a few words about Either and Ior, which I think it's the part most developer can immediately understand. I think the Raise DSL requires some additional investment, so I've added it at the end of the section. WDYT?

serras commented 10 months ago

I've added some additional documentation in relation to https://github.com/arrow-kt/arrow/pull/3299