https://kotlinlang.org logo
Join Slack
Channels
announcements
100daysofcode
100daysofkotlin
100daysofkotlin-2021
advent-of-code
aem
ai
akkurate
alexa
algeria
algolialibraries
amper
amsterdam
android
android-architecture
android-databinding
androidgithubprojects
android-studio
androidthings
androidx
androidx-xprocessing
anime
anko
apollo-kotlin
appintro
appyx
arabic
argentina
arkenv
arksemdevteam
armenia
arrow
arrow-contributors
arrow-meta
ass
atlanta
atm17
atrium
austin
australia
austria
awesome-kotlin
aws-sdk
ballast
bangladesh
barcelona
bayarea
bazel
beepiz-libraries
belgium
benchmarks
berlin
big-data
books
boston
brazil
brikk
budapest
build
build-tools
bulgaria
bydgoszcz
cambodia
canada
carrat
carrat-dev
carrat-feed
chennai
chicago
chile
china
chucker
cincinnati-user-group
cli
clikt
cloudfoundry
cn
cobalt
code-coverage
codeforces
codemash-precompiler
codereview
codingame
codingconventions
coimbatore
collaborations
colombia
colorado
communities
competitivecoding
competitive-programming
compiler
compose
compose-android
compose-desktop
compose-destinations
compose-hiring
compose-ios
compose-mp
compose-ui-showcase
compose-wear
compose-web
confetti
connect-audit-events
corda
cork
coroutines
couchbase
coursera
croatia
cryptography
cscenter-course-2016
cucumber-bdd
cup-presentations
cyprus
czech
dagger
data2viz
databinding
datascience
dckotlin
debugging
decompose
decouple
denmark
dependency-injection
deprecated
detekt
detekt-hint
dev-core
dfw
docs-revamped
dokka
domain-driven-design
doodle
dsl
dublin
dutch
eap
eclipse
ecuador
edinburgh
education
effectivekotlin
effective-kotlin
emacs
embedded-kotlin
estatik
event21-community-content
events
exposed
failgood
fb-internal-demo
feed
firebase
fleet
flow
flowmvi
fluid-libraries
forkhandles
forum
fosdem
fp-in-kotlin
framework-elide
freenode
french
fritz2
fuchsia
fun-adaptive
functional
funktionale
gamedev
ge-kotlin
general-advice
georgia
geospatial
german-lang
getting-started
github-workflows-kt
glance
godot-kotlin
google-io
gradle
graphic
graphkool
graphql
graphql-kotlin
graviton-browser
greece
grpc
gsoc
gsoc-compose-multiplatform-storybook
gsoc-ij-gradle-plugin
gsoc-kmp-bazel
gsoc-kmp-bazel
gsoc-kmp-gemini-firebase
gsoc-kotlin-bom-bazel
gsoc-kotlin-lsp-project
gsoc-kotlin-openrewrite
gsoc-wasm-incremental-compilation
gui
hackathons
hamburg
hamkrest
helios
helsinki
hexagon
hibernate
hikari-cp
hire-me
hiring
hiring-french
hongkong
hoplite
http4k
hungary
hyderabad
image-processing
india
indonesia
inkremental
intellij
intellij-plugins
intellij-tricks
internships
introduce-yourself
io
ios
iran
israel
istanbulcoders
italian
j2k
jackson-kotlin
jadx
japanese
jasync-sql
javadevelopers
javafx
javalin
javascript
java-to-kotlin-refactoring
jdbi
jewel
jhipster-kotlin
jobsworldwide
jpa
jshdq
juul-libraries
jvm
jvm-ir-backend-feedback
jxadapter
k2-adopters
kaal
kafka
kakao
kalasim
kapt
karachi
karg
karlsruhe
kash_shell
kaskade
kbuild
kdbc
kgen-doc-tools
kgraphql
kilua
kinta
klaxon
klibs-io
klock
kloudformation
kmdc
kmm-español
kmongo
knbt
knote
koalaql
koans
kobalt
kobweb
kodein
kodex
kohesive
koin
koin-contributors
komapper
kondor-json
kong
konsist
konsist-dev
kontent
kontributors
koog-agentic-framework
korau
kore
korean
korge
korim
korio
korlibs
korte
kotest
kotest-contributors
kotless
kotlick
kotlinacademy
kotlin-asia
kotlin-beam
kotlinbot
kotlin-by-example
kotlinconf
kotlin-csv
kotlin-data-storage
kotlindl
kotlinforbeginners
kotlin-foundation
kotlin-fuel
kotlingforbeginners
kotlin-in-action
kotlin-inject
kotlin-kinetics
kotlin-latam
kotlin-logging
kotlinlondon
kotlinmad
kotlin-multiplatform-contest
kotlin-mumbai
kotlin-native
kotlin-pakistan
kotlin-plugin
kotlinprogrammers
kotlin-pune
kotlin-roadmap
kotlin-samples
kotlin-sap
kotlin-serbia
kotlin-spark
kotlinsu
kotlin-szeged
kotlintest
kotlintest-devs
kotlintlv
kotlinultimatechallenge
kotlin-website
kotlinx-collections-immutable
kotlinx-datetime
kotlinx-files
kotlinx-html
kotlinx-rpc
kotools
kotrix
kotson
kotzilla-platform
kovenant
kprompt
kraph
krawler
kroto-plus
ksp
kstatemachine
ktcc
ktfmt
ktlint
ktor
ktp
kubed
kug-leads
kug-torino
kvision
kweb
lambdaworld_cadiz
lanark
language-evolution
language-proposals
latvia
leakcanary
leedskotlinusergroup
lets-have-fun
libgdx
libkgd
library-development
lincheck
linenbot
linkeddata
lithuania
london
losangeles
lottie
love
lychee
macedonia
machinelearningbawas
madrid
malaysia
mathematics
meetkotlin
memes
meta
metro-detroit
mexico
miami
micronaut
minnesota
minutest
mirror
mockk
moko
moldova
monsterpuzzle
montreal
moonbean
morocco
motionlayout
mpapt
mu
multiplatform
mumbai
munich
mvikotlin
mvrx
myndocs-oauth2-server
naming
navigation-architecture-component
nepal
new-mexico
newname
new-zealand
nigeria
nodejs
norway
npm-publish
nyc
oceania
ohio-kotlin-users
oldenburg
olpaka
oolong
opensavvy
opensource
orbit-mvi
osgi
otpisani
package-search
pakistan
panamá
parameterize
pattern-matching
pbandk
pdx
peru
philippines
phoenix
pinoy
pocketgitclient
polish
popkorn
portugal
power-assert
practical-functional-programming
proguard
prozis-android-backup
pyhsikal
python
python-contributors
quasar
random
re
react
reaktive
realm
realworldkotlin
reductor
reduks
redux
redux-kotlin
refactoring-to-kotlin
reflect
refreshversions
reports
result
rethink
revolver
rhein-main
rocksdb
romania
room
rpi-pico
rsocket
russian
russian_feed
russian-kotlinasfirst
rx
rxjava
san-diego
science
scotland
scrcast
scrimage
script
scripting
seattle
serialization
server
sg-user-group
singapore
skia-wasm-interop-temp
skrape-it
slovak
snake
sofl-user-group
southafrica
spacemacs
spain
spanish
speaking
spek
spin
splitties
spotify-mobius
spring
spring-security
squarelibraries
stackoverflow
stacks
stayhungrystayfoolish
stdlib
stlouis
store
storyboard
storytale
strife-discord-lib
strikt
students
stuttgart
sudan
supabase-kt
swagger-gradle-codegen
swarm
sweden
swift-export
swing
swiss-user-group
switzerland
talking-kotlin
tallinn
tampa
teamcity
tegal
tempe
tensorflow
terminal
terpal
test
testing
testtestest
texas
tgbotapi
thailand
tornadofx
touchlab-tools
training
tricity-kotlin-user-group
trójmiasto
truth
tunisia
turkey
turkiye
twitter-feed
uae
udacityindia
uk
ukrainian
uniflow
unkonf
uruguay
utah
uuid
vancouver
vankotlin
vertx
videos
vienna
vietnam
vilnius-kug
vim
vkug
vuejs
webassembly
web-mpp
webrtc
wimix_sentry
wwdc
zircon
Powered by
# arrow
  • m

    Marc

    04/22/2025, 10:01 AM
    hey guys,
    kotest-extensions-arrow
    have ben move to read only. could someone tell me what i the alternative we have to use now? 🙏🏻
    p
    • 2
    • 3
  • e

    Emil Kantis

    04/22/2025, 2:18 PM
    I'm getting issues when trying to serialize a non-empty list using Jackson. (Arrow 2.1.0, Jackson 2.18.3)
    ✅ 1
    a
    • 2
    • 5
  • a

    Alejandro Serrano.Mena

    04/22/2025, 7:08 PM
    more releases this week: Arrow plug-in for IntelliJ now features gutter icons for
    Raise
    https://arrow-kt.io/community/blog/2025/04/22/arrow-intellij-0-3/
    arrow intensifies 7
    K 11
    🤩 4
    amaze 1
    e
    l
    • 3
    • 16
  • a

    Artūras Šlajus

    04/23/2025, 9:08 AM
    Hey. Kotlin doesn’t have union types, right? I can’t take do this, right?
    Copy code
    val v1: Validator<E1>
    val v2: Validator<E2>
    
    listOf(v1, v2): List<Validator<E1 | E2>>
    a
    j
    • 3
    • 12
  • f

    Fred Friis

    04/25/2025, 3:36 PM
    trying to add Arrow 2.1.0 to one of our repos and getting this error (more in screenshots)
    Copy code
    some kotlin runtime libraries have an unsupported binary format
    Copy code
    some kotlin runtime libraries and 6 other jars have an unsupported binary format
    my understanding is this repo has kotlin 1.9 so what's the dealio?
    a
    p
    • 3
    • 3
  • a

    aykrieger

    04/26/2025, 2:27 AM
    Hi all, I would like to use the concept of "errors as values" instead of throwing exceptions when I validate the data of a newly instantiated class. Before, to ensure my data was validated I would use the
    init{ }
    block and this would throw an exception if the data given in the constructor was invalid. Example:
    Copy code
    @JvmInline
    value class Foo(
        val bar: String,
    ) {
        init {
            require(bar.isNotBlank())
        }
    }
    I was thinking I could use the
    Either
    class and a companion object to validate the data when calling
    create
    without throwing an exception.
    Copy code
    @JvmInline
    value class Foo(
        val bar: String,
    ) {
        companion object {
            fun create(bar: String): Either<Error, Foo> =
                if (bar.isNotBlank()) {
                    Foo(bar).right()
                } else {
                    IsBlankString().left()
                }
            }
        }
    }
    
    sealed interface Error {
        class IsBlankString: Error
    }
    The issue is that I can't make the
    Foo
    constructor
    Foo(val bar: String)
    private for
    value class
    or
    data class
    . So I can't guarantee that the property
    bar
    has been validated if someone creates
    Foo
    with
    Foo("")
    instead of
    Foo.create("")
    . I tried changing the function name from
    create
    to
    invoke
    to possibly override the constructor but it seems the Kotlin compiler picks the constructor
    Foo(val bar: String)
    instead of the
    invoke
    function when calling
    Foo("")
    . I understand I can achieve this with a regular
    class
    and use a private constructor, but I haven't been able to achieve this with a
    value class
    or
    data class
    . I would like have the auto-generated
    copy()
    and
    equals()
    functions that
    data classes
    provides. I read this article and they have an interesting solution for this issue by using a
    sealed interface
    to validate a
    data class
    . When I tried this solution, I wasn't able to use the
    .copy()
    function normally auto-generated for
    data class
    . So there are some tradeoffs. Link: https://proandroiddev.com/how-to-use-arrows-either-for-exception-handling-in-your-application-a73574b39d07 Does anyone have any recommendations or solutions you have used to solve this issue?
    e
    a
    a
    • 4
    • 6
  • a

    Alen Mujezinovic

    04/29/2025, 2:57 PM
    Hey folks. Has someone considered the use case of using optics together with
    private constructor
    and
    @ConsistentCopyVisibility?
    There are cases where
    copy
    should only be available to other methods of the class and therefore be private, e.g. when modelling state changes that require $otherThings to happen before
    copy
    can be safely called.
    y
    • 2
    • 2
  • a

    Alejandro Serrano.Mena

    04/29/2025, 3:26 PM
    there is a new 2.1.1 release of Arrow! this is mostly a bugfix release: • fixed problems with Jackson serialization • made it possible to use Arrow with Android SDK > 21 (before it was >24) we also added a new wrapAsNonEmpty family of functions to avoid copying when creating a NonEmptyThing
    arrow intensifies 9
    s
    • 2
    • 2
  • c

    carbaj0

    04/30/2025, 5:54 AM
    I understand that in the final version of the context parameters this will not be an error, right?
    s
    p
    • 3
    • 6
  • y

    Youssef Shoaib [MOD]

    04/30/2025, 9:29 AM
    A fun oddity:
    AutoCloseScope
    can do reverse-mode automatic differentiation:
    Copy code
    interface AD<Num> {
      val Double.num: Num
      val Int.num: Num get() = toDouble().num
      operator fun Num.plus(other: Num): Num
      operator fun Num.times(other: Num): Num
      fun exp(x: Num): Num
    }
    data class NumB(val value: Double, var d: Double)
    
    fun backwardsAutoClose(x: Double, prog: AD<NumB>.(NumB) -> NumB): Double {
      val input = NumB(x, 0.0)
      autoCloseScope {
        val res = object : AD<NumB> {
          override val Double.num: NumB get() = NumB(this, 0.0)
          override fun NumB.plus(other: NumB) = NumB(value + other.value, 0.0).also { z ->
            onClose {
              this.d += z.d
              other.d += z.d
            }
          }
    
          override fun NumB.times(other: NumB) = NumB(value * other.value, 0.0).also { z ->
            onClose {
              d += other.value * z.d
              other.d += value * z.d
            }
          }
    
          override fun exp(x: NumB): NumB {
            val xExp = mathExp(x.value)
            val z = NumB(xExp, 0.0)
            onClose { x.d += xExp * z.d }
            return z
          }
        }.prog(input)
        res.d += 1
      }
      return input.d
    }
    arrow intensifies 1
    K 1
  • g

    gpopides

    04/30/2025, 11:53 AM
    not sure what the issue is, but the docs here seem a bit off regarding the type parameter A https://apidocs.arrow-kt.io/arrow-fx-coroutines/arrow.fx.coroutines/closeable.html
    s
    • 2
    • 4
  • e

    Edgar Avuzi

    05/02/2025, 6:10 AM
    Is there a doc, guide or article on how to manage stacktrace while working with https://arrow-kt.io/learn/typed-errors/ ?
    y
    s
    • 3
    • 10
  • y

    Youssef Shoaib [MOD]

    05/03/2025, 11:55 PM
    Raise proves the law of the excluded middle (well, something equivalent to it anyway)!
    Copy code
    inline fun <A> doubleNegationElimination(block: ((A) -> Nothing) -> Nothing): A = merge { block(this::raise) }
    For more info Bonus:
    suspend
    allows the same thing (which is precisely why early raise builders were made using
    suspend
    magic):
    Copy code
    suspend fun <A> doubleNegationElimination(block: suspend (suspend (A) -> Nothing) -> Nothing): A = suspendCoroutine { cont ->
        block.startCoroutine({ value ->
            suspendCoroutine<Nothing> {
                cont.resume(value)
            }
        }, cont)
    }
    arrow intensifies 1
    s
    • 2
    • 2
  • m

    Marc

    05/07/2025, 2:34 PM
    doesn’t feel a bit odd using the Raise api with context params? with context receivers was feeling way more natural IMO
    Copy code
    context(raise: Raise<DomainError>)
    fun <T> HttpClient.getSomethingFromNetwork(): T = with(raise) {
        // network operator | raise(DomainError)
    }
    not sure if that’s the only way tho , but it feels odd the need to scope raise now 😕
    a
    • 2
    • 2
  • s

    Stephen Morse

    05/15/2025, 2:53 PM
    Can anyone here tell me how significant the binary compatibility issues are for
    NonEmptyList
    (using
    NonEmptyListSerializer
    ) between Arrow v1 and v2? My company (Cash App/Block) has some data serialized with the
    NonEmptyListSerializer
    of Arrow v1, but we need to upgrade to Arrow v2. Is it possible to define a serializer that can deserialize both the v1 and v2 binary formats? 🤔
    y
    p
    +2
    • 5
    • 8
  • d

    dawidhyzy

    05/16/2025, 8:15 AM
    Is it possible to recover from multiple errors with raise? For example having such function:
    Copy code
    context(_: Raise<StreamError>, _ : Raise<ServiceError.Expected>)
    suspend fun getLiveStream(url: ChannelStreamUrl): Stream
    a
    y
    • 3
    • 6
  • a

    Alejandro Serrano.Mena

    05/16/2025, 2:36 PM
    new 2.1.2 released! it has a few bug fixes, and lowers the required JVM to 1.8 (except for the Compose module)
    K 4
    arrow intensifies 11
  • g

    Geert

    05/20/2025, 7:40 AM
    Hi, I’m a bit stuck on optics, I’m trying to “match” the last element of an array, from within a copy method, something like this:
    Copy code
    person.copy {
        Person.names.last transform { it.replaceFirstChar(Char::uppercase) }
    }
    Of course the
    last
    val does not exist, but is there some way to do this?
    a
    • 2
    • 2
  • j

    jean

    05/23/2025, 10:50 AM
    Does anyone has insights in the “Rich errors” feature that was announced? It looked similar to what
    Either
    does, didn’t it?
    d
    e
    +3
    • 6
    • 10
  • y

    Youssef Shoaib [MOD]

    05/25/2025, 8:27 PM
    Raise
    can be used to implement first-class generic lambdas (i.e rank-2 polymorphism)!
    Copy code
    import arrow.core.raise.Raise
    import arrow.core.raise.merge
    
    private fun main() {
      println("Identity:")
      useIdentity {
        raise.raise(value)
      }
      println("ListMaker: ")
      useListMaker {
        // "opening" an existential type
        // ideally, this would work like the example above through compiler magic
        fun <A> ListMaker<A>.block(): Nothing = raise.raise(listOf(value))
        block()
      }
      useListMaker {
        fun <A> ListMaker<A>.dishonest(): Nothing = when (value) {
          is Unit -> raise.raise(listOf())
          is Int -> raise.raise(listOf(value))
          else -> raise.raise(listOf(value, value))
        }
        dishonest()
      }
      println("Choice: ")
      useChoice {
        raise.raise(second)
      }
      useChoice {
        fun <A> Choice<A>.dishonest(): Nothing = when (first) {
          is Unit -> raise.raise(second)
          is Int -> raise.raise(first)
          else -> raise.raise(second)
        }
        dishonest()
      }
    }
    
    private class Identity<A>(val value: A, val raise: Raise<A>)
    
    private fun useIdentity(block: Identity<*>.() -> Nothing) {
      val value = merge {
        Identity(Unit, this).block()
      }
      println(value)
      val value2 = merge {
        Identity(42, this).block()
      }
      println(value2)
    }
    
    private class ListMaker<A>(val value: A, val raise: Raise<List<A>>)
    
    private fun useListMaker(block: ListMaker<*>.() -> Nothing) {
      // we can convert this to a List<Unit>, which is equivalent to an Int
      val listValue = merge {
        ListMaker(Unit, this).block()
      }
      println(listValue)
      val listValue2 = merge {
        ListMaker(42, this).block()
      }
      println(listValue2)
      // We can always keep the polymorphic function honest by wrapping in an unreachable type
      // Using data class for clarity, but ideally you want a type that returns the same
      // toString and same hashCode for all instances.
      data class Wrapper<A>(val value: A)
    
      val wrappedValue = merge {
        ListMaker(Wrapper(Unit), this).block()
      }
      println(wrappedValue)
      // hence it can't know the type of the value inside without reflection
      // (but with reflection, all bets are off anyway)
      val wrappedValue2 = merge {
        ListMaker(Wrapper(42), this).block()
      }
      println(wrappedValue2)
    }
    
    private class Choice<A>(val first: A, val second: A, val raise: Raise<A>)
    
    private fun useChoice(block: Choice<*>.() -> Nothing) {
      // we can convert this to a Boolean
      val value = merge {
        Choice(false, true, this).block()
      }
      println(value)
      val value2 = merge {
        Choice(41, 42, this).block()
      }
      println(value2)
      // Keeping it honest, just like in ListMaker
      data class Wrapper<A>(val value: A)
    
      val wrappedValue = merge {
        Choice(Wrapper(false), Wrapper(true), this).block()
      }
      println(wrappedValue)
      // so results are identical here
      val wrappedValue2 = merge {
        Choice(Wrapper(41), Wrapper(42), this).block()
      }
      println(wrappedValue2)
    }
    It turns out we can very easily implement generic lambdas (i.e. lambdas like
    <A> (A) -> List<A>
    ) without direct language support! Of course, we could already use a (not-
    fun
    )
    interface ListMaker { fun <A> make(a: A): List<A> }
    , but that'd require making an anonymous object at the call site, which has awkward syntax, and cannot be made
    inline
    . Instead, we can define it directly by giving the lambda only one way to exist, which is to
    raise
    something of an existentially-quantified type, while also potentially giving it several members of that unknown type. Sadly, the compiler isn't super smart at the moment in dealing with existential types. It can handle some of them in very, very simple cases (as shown in the
    useIdentity
    example), but it gives up whenever there's any function call in between (like
    listOf
    , for instance). Hopefully the compiler can get smarter in the future!
    🧵 1
    👀 1
    • 1
    • 2
  • j

    jean

    05/30/2025, 7:28 AM
    I’m migrating an old codebase from 1.1.5 to 2.1.2. What’s a good replacement for
    parTraverse
    ? I see the migration guide recommands
    mapOrAccumulate
    but does it have the
    parrallelle
    capabilities too?
    s
    • 2
    • 6
  • d

    dave08

    06/05/2025, 4:39 PM
    Is there any recoverCatching in the Either.catch api (something like in Kotlin's Result, where you can chain a few potentially failing operations and still have a fallback), w/o nesting catches?
    s
    c
    • 3
    • 14
  • j

    J.D. Satlin

    06/10/2025, 12:42 AM
    I've found myself reaching for and unable to find a totally comfortable way to take an already existing either's right value, and under some condition turn it into a value in the left channel. Sort of the opposite of a
    recover
    . Sometimes this is a sign to turn a function into one that takes a raise context overall, but sometimes that feels less advisable (public functions, that then become less discoverable because they require the raise context, mostly. That might be its own discussion). About the simplest version I've got is below, but I'm wondering if there's just something I'm missing in how to do this more easily than a flatmap?
    Copy code
    fun randomNumber(): Either<String, Int> {
        val randomNum = Random(1).nextInt(1..10)
    
        return if (randomNum > 5) {
            randomNum.right()
        } else {
            "The number was too low".left()
        }
    }
    
    fun failOnMoreConditions(): Either<String, Int> {
        return randomNumber()
            .flatMap { num ->
               either {
                   ensure(num != 10) { "Number 10 also not allowed" }
                   num
               }
        }
    }
    y
    a
    • 3
    • 16
  • s

    S.

    06/11/2025, 3:04 PM
    How do I correctly use
    either {}
    in combination with
    flow {}
    ? when I have a function like this
    Copy code
    fun list(): Either<Error, Flow<Item>> = either { 
        flow {
            if (someSuspendFun()) this@either.raise(Error)
        emitAll(someList())
        }
    }
    it says
    arrow.core.raise.RaiseLeakedException: 'raise' or 'bind' was leaked outside of its context scope. Make sure all calls to 'raise' and 'bind' occur within the lifecycle of nullable { }, either { } or similar builders.
    or is the way to go to make the function suspend and do the check before the flow block?
    s
    • 2
    • 4
  • e

    Erik Dreyer

    06/12/2025, 4:19 PM
    When using
    Either.catch()
    I find myself wanting to treat it like
    either {}
    and use various DSL methods provided by
    Raise
    inside the catch() function. Since it doesn't provide that context, is this the correct way?
    Copy code
    either {
        Either.catch() { ... }.bind()
    }
    y
    s
    • 3
    • 10
  • k

    Kjartan

    06/25/2025, 5:50 AM
    Does anyone know if the new DI feature introduced in Ktor 3.2.0 will replace the need for using Arrows SuspendApp with Ktor lib?
    s
    • 2
    • 4
  • k

    Kev

    06/30/2025, 6:28 AM
    In Arrow 1.2.4, why is the construction of CircuitBreaker a suspendable function? What strategy can I use to create a shared CircuitBreaker to be used across multiple API method calls?
    s
    • 2
    • 3
  • m

    Michael Friend

    07/01/2025, 6:30 PM
    Posted this as a comment on the PR for raise context param support but figured id crosspost here to start a conversation and see if anyone has workaround ideas. TLDR with an inline function that takes a
    block: context(Raise<Error>) () -> T
    parameter, calling the function within an
    either
    builder causes some ambiguity between the extension function raise variants like
    Raise<E>.raise()
    you can call on the receiver on the
    either
    block and the
    context(Raise<E>) raise()
    variant available on the context parameter on block which makes it easy to raise an error on the either block rather than within the block parameter
    • 1
    • 3
  • o

    Olaf Gottschalk

    07/08/2025, 3:18 PM
    I got a question regarding resources for you. In my use case, I have an application that has to start/manage/shutdown entities called
    Server
    - which is defined as an
    interface
    . So it looks along the lines of this:
    Copy code
    interface Server {
      fun prepare()
      fun run()
      fun shutdown()
    }
    In order to properly handle these as resources, I have some
    fun execute()
    that does this:
    Copy code
    fun execute() {
      resourceScope {
        servers.forEach {
          install({ it.prepare() }, { _, _ -> it.shutdown() })
        }
        servers.forEach(Server::run)
      }
    }
    Now, this assumes that all
    Server
    classes basically can do all of there setup in
    prepare
    and properly release all resources in
    shutdown
    . In some servers though, I would like to also use the resource concept and install things in the same resource scope to allow them to live alongside the servers and properly get shutdown as well. Those types of server implementations typically do not define any code in their
    shutdown
    function, but they want to install more resources in the same resource scope. That's why I extended my
    prepare
    fun like this:
    Copy code
    interface Server {
      context(ResourceScope) fun prepare()
      fun run()
      fun shutdown()
    }
    To now execute my system, I need to manually bring the resource scope back into scope:
    Copy code
    fun execute() {
      resourceScope {
        servers.forEach {
          install({ context(this@resourceScope) { it.prepare() } }, { _, _ -> it.shutdown() })
        }
        servers.forEach(Server::run)
      }
    }
    Now the big question: am I doing something wrong? Is it safe to hand in the same resource scope into the acquire step of a resource so this resource can also install resources in the same scope? Note: the reason I do this is that I got several different types of Server implementations, some that need a "classic" prepare/shutdown step, others that are fine with installing resources!
    s
    y
    a
    • 4
    • 12
  • r

    raulraja

    07/17/2025, 5:19 PM
    https://deepwiki.com/arrow-kt/arrow This works surprisingly well to get info about arrow's apis
    arrow intensifies 2
    y
    • 2
    • 2