https://kotlinlang.org logo
Join the conversationJoin Slack
Channels
100daysofcode
100daysofkotlin
100daysofkotlin-2021
advent-of-code
aem
ai
alexa
algeria
algolialibraries
amsterdam
android
android-architecture
android-databinding
android-studio
androidgithubprojects
androidthings
androidx
androidx-xprocessing
anime
anko
announcements
apollo-kotlin
appintro
arabic
argentina
arkenv
arksemdevteam
armenia
arrow
arrow-contributors
arrow-meta
ass
atlanta
atm17
atrium
austin
australia
austria
awesome-kotlin
ballast
bangladesh
barcelona
bayarea
bazel
beepiz-libraries
belgium
berlin
big-data
books
boston
brazil
brikk
budapest
build
build-tools
bulgaria
bydgoszcz
cambodia
canada
carrat
carrat-dev
carrat-feed
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
competitive-programming
competitivecoding
compiler
compose
compose-android
compose-desktop
compose-hiring
compose-ios
compose-mp
compose-ui-showcase
compose-wear
compose-web
connect-audit-events
corda
cork
coroutines
couchbase
coursera
croatia
cryptography
cscenter-course-2016
cucumber-bdd
cyprus
czech
dagger
data2viz
databinding
datascience
dckotlin
debugging
decompose
decouple
denmark
deprecated
detekt
detekt-hint
dev-core
dfw
docs-revamped
dokka
domain-driven-design
doodle
dsl
dublin
dutch
eap
eclipse
ecuador
edinburgh
education
effective-kotlin
effectivekotlin
emacs
embedded-kotlin
estatik
event21-community-content
events
exposed
failgood
fb-internal-demo
feed
firebase
flow
fluid-libraries
forkhandles
forum
fosdem
fp-in-kotlin
framework-elide
freenode
french
fritz2
fuchsia
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
gui
hackathons
hacktoberfest
hamburg
hamkrest
helios
helsinki
hexagon
hibernate
hikari-cp
hire-me
hiring
hongkong
hoplite
http4k
hungary
hyderabad
image-processing
india
indonesia
inkremental
intellij
intellij-plugins
intellij-tricks
internships
introduce-yourself
io
ios
iran
israel
istanbulcoders
italian
jackson-kotlin
jadx
japanese
jasync-sql
java-to-kotlin-refactoring
javadevelopers
javafx
javalin
javascript
jdbi
jhipster-kotlin
jobsworldwide
jpa
jshdq
juul-libraries
jvm-ir-backend-feedback
jxadapter
k2-early-adopters
kaal
kafka
kakao
kalasim
kapt
karachi
karg
karlsruhe
kash_shell
kaskade
kbuild
kdbc
kgen-doc-tools
kgraphql
kinta
klaxon
klock
kloudformation
kmdc
kmm-español
kmongo
knbt
knote
koalaql
koans
kobalt
kobweb
kodein
kodex
kohesive
koin
koin-dev
komapper
kondor-json
kong
kontent
kontributors
korau
korean
korge
korim
korio
korlibs
korte
kotest
kotest-contributors
kotless
kotlick
kotlin-asia
kotlin-beam
kotlin-by-example
kotlin-csv
kotlin-data-storage
kotlin-foundation
kotlin-fuel
kotlin-in-action
kotlin-inject
kotlin-latam
kotlin-logging
kotlin-multiplatform-contest
kotlin-mumbai
kotlin-native
kotlin-pakistan
kotlin-plugin
kotlin-pune
kotlin-roadmap
kotlin-samples
kotlin-sap
kotlin-serbia
kotlin-spark
kotlin-szeged
kotlin-website
kotlinacademy
kotlinbot
kotlinconf
kotlindl
kotlinforbeginners
kotlingforbeginners
kotlinlondon
kotlinmad
kotlinprogrammers
kotlinsu
kotlintest
kotlintest-devs
kotlintlv
kotlinultimatechallenge
kotlinx-datetime
kotlinx-files
kotlinx-html
kotrix
kotson
kovenant
kprompt
kraph
krawler
kroto-plus
ksp
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
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
new-zealand
newname
nigeria
nodejs
norway
npm-publish
nyc
oceania
ohio-kotlin-users
oldenburg
oolong
opensource
orbit-mvi
osgi
otpisani
package-search
pakistan
panamá
pattern-matching
pbandk
pdx
peru
philippines
phoenix
pinoy
pocketgitclient
polish
popkorn
portugal
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
strife-discord-lib
strikt
students
stuttgart
sudan
swagger-gradle-codegen
swarm
sweden
swing
swiss-user-group
switzerland
talking-kotlin
tallinn
tampa
teamcity
tegal
tempe
tensorflow
terminal
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
vim
vkug
vuejs
web-mpp
webassembly
webrtc
wimix_sentry
wwdc
zircon
Powered by Linen
arrow
  • l

    Luke

    06/22/2022, 2:50 PM
    In Arrow Optics, is there an equivalent of 'lift' but just to get the value? I have something like
    val getId: (MyClass) -> String? = MyClass.somePath.id::getOrNull
    , which works, but I would prefer to call a method instead of
    ::getOrNull
    to return a lambda directly so I don't have to explicit the variable type.
    s
    • 2
    • 4
  • e

    Erik Dreyer

    06/22/2022, 8:37 PM
    Is there a way in Arrow to achieve a
    flatMap
    like operation with two methods that produce
    ValidatedNel<E,A>
    where the “right” side of the first method is an input into the second method?
    d
    r
    • 3
    • 27
  • m

    Moritz Lindner

    06/23/2022, 12:47 PM
    Hi 🙂 My team heavily uses the
    either.eager
    -For-Comprehensions. Do you have any tips regarding debugging? It can get quite cumbersome sometimes because of the actual execution in either.eager? Regards 🙂
    s
    • 2
    • 1
  • n

    Nathan Bedell

    06/23/2022, 3:18 PM
    Hey all, curious if there's a version of arrow-optics that will work with 1.7.0 yet (even if alpha).
    s
    • 2
    • 1
  • o

    Ollis

    06/24/2022, 5:57 PM
    Hi, does anyone know if this feature is to be expected soon: https://github.com/arrow-kt/arrow-core/issues/203 I really miss the opportunity to compose suspended functions 😄
    n
    s
    • 3
    • 3
  • p

    Partho Paul

    06/25/2022, 2:32 PM
    Hi, I want to do a nested validation on my input request body. I did it as below:
    fun InputRequest.validate(): Validated<IncorrectInput, InputRequest> =
        userType.validateMail(obj.inputEnum)
            .zip(username.validateUserName(), obj.validateObj()) {
                    userType,
                    userName,
                    obj ->
                InputRequest(userType, userName, obj)
            }
            .mapLeft(::IncorrectInput)
    
    fun String.validateUserType(enum: Enum):ValidatedNel<InvalidUserType, String> {
        val trimmed = trim()
        if(trimmed.isBlank()) {
            return "User type can't be empty".invalidNel().mapLeft(toInvalidField(::InvalidUserType))
        }
        if(trimmed == "other" && !(enum == Enum.E1 || enum == Enum.E2)) {
            return "Given user type is not supported with E1 and E2".invalidNel().mapLeft(toInvalidField(::InvalidMail))
        }
        return validNel()
    }
    In the above code,
    validateUserType
    looks a bit dirty to me. Is there a better to do the same?
    m
    s
    • 3
    • 3
  • g

    Gopal S Akshintala

    06/27/2022, 2:09 PM
    Hi, can I achieve this with arrow-fx, this article got me curious: https://arrow-kt.io/docs/apidocs/arrow-fx-coroutines/arrow.fx.coroutines/-schedule/ Is there an example, that uses persistence to suspend and resume a thread/job?
    s
    s
    • 3
    • 29
  • l

    Lukasz Kalnik

    06/30/2022, 9:21 AM
    Can I build, using Arrow, a custom, generic sum type similar to
    Either
    but with more subtypes? I need something like this:
    sealed class DataState<T> {
    
        class Loading<T> : DataState<T>()
    
        data class Error<T>(val error: CallError) : DataState<T>()
    
        data class DataLoaded<T>(
            val data: T
        ) : DataState<T>()
    }
    And I want only the
    DataLoaded
    subtype to behave as
    Either.Right
    (e.g. when using
    flatMap()
    ) and all other subtypes behave as
    Either.Left
    , i.e. having early returns from
    flatMap()
    . I especially would like to have the monad comprehension syntax analogous to the
    either {}
    DSL (using
    .bind()
    ).
    y
    s
    • 3
    • 5
  • l

    Lukasz Kalnik

    06/30/2022, 12:32 PM
    Can one use the
    either {}
    monad comprehension also outside suspending context? I want to use it in a non-suspending function, but it seems that
    arrow.core.continuations.either
    only has a suspending version of `invoke()`:
    public suspend operator fun <E, A> invoke(f: suspend EffectScope<E>.() -> A): Either<E, A> =
        effect(f).toEither()
    s
    • 2
    • 1
  • l

    Lukasz Kalnik

    07/01/2022, 3:11 PM
    Is there some clever way in Arrow to check a list of nullable values if any of them
    != null
    Apart from the standard syntax:
    myVal1 != null || myVal2 != null || myVal3 != null
    This is ok, but I would like to write something more expressive, like:
    listOf(myVal1, myVal2, myVal3).anyNotNull()
    a
    • 2
    • 7
  • l

    Lukasz Kalnik

    07/04/2022, 8:50 AM
    For some reason the
    bind()
    on the
    Either
    contained in the `MutableStateFlow`'s
    value
    here cannot be resolved.
    commonConnectorApi.renameControlDevice()
    returns
    Either<CallError, Unit>
    .
    s
    a
    • 3
    • 11
  • t

    thanh

    07/04/2022, 10:21 AM
    Do we have something like this in Arrow? I tried to find but it seems missing.
    public fun <A, B, C> Either<A, B>.combine(SGA: Semigroup<A>, b: Either<A, C>): Either<A, Pair<B, C>>
    s
    s
    +3
    • 6
    • 25
  • l

    Lukasz Kalnik

    07/08/2022, 2:20 PM
    I added to my build.gradle.kts:
    plugins {
        id("com.google.devtools.ksp")
    }
    
    dependencies {
        implementation("io.arrow-kt:arrow-optics:$arrowVersion")
        ksp("io.arrow-kt:arrow-optics-ksp-plugin:$arrowVersion")
    }
    I have also annotated my data classes:
    @optics
    data class ConnectorWithSensors(
        val connector: Connector,
        val sensors: List<ItemSelection>,
    ) {
        companion object
    }
    
    @optics
    data class ItemSelection(
        val id: String,
        val selected: Boolean,
    ) : {
        companion object
    }
    However I cannot access the extensions generated on companion object like
    ConnectorWithSensors.sensors
    .
    a
    • 2
    • 8
  • c

    Charlie Christensen

    07/08/2022, 2:27 PM
    I am experiencing a crash when using
    parZip
    inside of an
    either
    block.
    suspend fun refresh(): Either<Throwable, Unit> = either {
        parZip(
            { refreshA().bind() },
            { refreshB().bind() }
        ) { dataA, dataB ->
            persistData(dataA, dataB).bind()
        }
    }
    But if one of the suspending functions doesnt return the proper type, the exception is not caught. The crash happens with an unsafe cast at line 85 of
    ParZip.kt
    f(a as A, b as B)
    Is there any way to catch this exception? I feel like I would need to double wrap the Either
    s
    • 2
    • 1
  • y

    Youssef Shoaib [MOD]

    07/10/2022, 3:25 PM
    I asked about this a while back, but I honestly forgot where the conversation led to. Is there any update on an efficient
    Option
    encoding in Arrow using `value class`es? If there isn't anything proposed right now, I think I might've come up with one that instead of one
    None
    object it uses a
    None(Int)
    class that indicates the level of nesting of the
    Option
    (sort of similar to the
    Failure
    class used in
    Result
    ). If there hasn't been any successful experiments for a nested
    Option
    , I could make a PR in the next hour or so for one, if the arrow team sees that it is fit for the library.
    s
    • 2
    • 4
  • s

    Slackbot

    07/11/2022, 7:22 AM
    This message was deleted.
  • d

    Dirk

    07/11/2022, 9:04 AM
    I am having problems setting up lens generation in a multiplatform project. In step 3 of the setup I have the problem that the following error message is thrown by Gradle: "Type mismatch: inferred type is String but Action<KspExtension> was expected" Are multiplatform not supported or does the integration have to be done differently here?
    s
    • 2
    • 4
  • t

    Tower Guidev2

    07/11/2022, 11:05 AM
    Hi i thought i understood Either, then i tried employing
    io.arrow-kt:arrow-core-retrofit
    in my android application 🤦‍♂️
    s
    • 2
    • 7
  • s

    Satyam Agarwal

    07/12/2022, 11:38 AM
    I finally got time to try
    arrow-endpoint
    , but its not on 1.1.2 and all my apps are now on 1.1.2 Can I help in bumping versions and releasing ? cc: @simon.vergauwen
    s
    • 2
    • 26
  • j

    jrgonzalez

    07/12/2022, 4:33 PM
    Hi, I’m trying to migrate some (network) Android code from Either to Effect and I’m getting weird crashes. Are the effect / Effect apis stable? Is there any known incompatibility with ktor? I have the happy path working now for some code, but whenever I try to do a shift my app crashes almost everytime. Debugger does not even stop on try-catches / folds, anything, it totally explodes bypassing all error handling. Stacktraces are like this:
    r
    • 2
    • 17
  • j

    jrgonzalez

    07/12/2022, 4:34 PM
    any idea?
  • j

    jrgonzalez

    07/12/2022, 4:35 PM
    there is also some kind of race condition involved cause even if I try to invoke shift before any ktor client call it still happens many times like if the shift was delayed
  • l

    Luke

    07/12/2022, 6:28 PM
    In optics, is there a way to "tap" on foci? I want to log stuff for debugging purposes. I'm searching for something like:
    MyClass.a.b.c.tap { println(it) }.d.e.f.set(state, newValue)
    s
    p
    • 3
    • 3
  • y

    Yannick Lazzari

    07/15/2022, 3:54 PM
    Hi all. Question regarding error handling inside an
    effect { ... }
    block. Given the following function:
    fun function1: Effect<ErrorAdt, String> = effect {
      val val1: String = function2()
      val val2: String = function3()
      return val1 + val2
    }
    and that both
    function2
    and
    function3
    are possibly throwing exceptions, what is the best way to convert any exceptions they might throw into my
    ErrorAdt
    ? Should I simply wrap each call to the functions inside
    try/catch
    blocks and convert them there? Or is there another error handling function that I can call on the effect, where I can centralize all error mapping logic, using some pattern matching on any thrown exceptions? I can't seem to find any in the docs, but just curious. Thank you!
    s
    s
    t
    • 4
    • 17
  • p

    phldavies

    07/19/2022, 2:48 PM
    Is there a timeline on an expected 1.1.3 release? Still very much dependent on alphas for the
    resource {}
    DSL release-order bug.
    s
    i
    • 3
    • 2
  • r

    rcd27

    07/21/2022, 10:51 AM
    I have a goal to inject some code invocations in my functions calls. Something like http://github.com/jakewharton/hugo (compiler plugin + AspectJ bytecode weaving + Android Gradle Transform API). And I remember
    Arrow
    team was working on better-compiler-plugin-environment-writing for Kotlin. Should I check it out?
    a
    j
    • 3
    • 10
  • r

    rcd27

    07/21/2022, 6:33 PM
    Today I've got a "coming out" from my partner: when I entered your project, I thought
    Either
    and
    FP
    in general is a b*llshit. Now I don't know how to write a good code without that. I send ❤️ to
    Arrow
    team, who have taught me that.
    ❤️ 1
    🔝 10
  • p

    phldavies

    07/22/2022, 1:18 PM
    Should this example throw or
    shift("boom")
    ?
    class Test : FreeSpec({
        "should this throw?" {
            effect {
                result { error("💥") }.bind { "boom" }
            }.toEither() shouldBe Either.Left("boom")
        }
    })
    Currently it throws.
    Either.catch({ "boom" }) { error("💥") }.bind()
    shifts as you’d expect.
    s
    • 2
    • 12
  • d

    dimsuz

    07/25/2022, 1:00 PM
    This probably was discussed before, but as a first-time arrow-optics user (it's great, thanks!), I wish adding
    @optics
    would automatically generate
    companion object
    if it's missing. I'm almost sure that this wasn't done because of some KSP/kotlin plugin API limitation, but maybe there's an issue I can vote on for Kotlin team to make this possible some day?
    s
    • 2
    • 2
  • n

    Nathan Bedell

    07/27/2022, 1:48 AM
    Are there any examples of implementing the
    nullable
    effect using the new Effect API (rather than the now deprecated one?). I am building what is essentially a modified version of
    nullable
    , so an example of
    nullable
    built with the new API would be very helpful. From what I can tell, it looks like currently (at least on main)
    nullable
    still uses the deprecated API.
    s
    y
    s
    • 4
    • 15
Powered by Linen
Title
n

Nathan Bedell

07/27/2022, 1:48 AM
Are there any examples of implementing the
nullable
effect using the new Effect API (rather than the now deprecated one?). I am building what is essentially a modified version of
nullable
, so an example of
nullable
built with the new API would be very helpful. From what I can tell, it looks like currently (at least on main)
nullable
still uses the deprecated API.
s

simon.vergauwen

07/27/2022, 6:25 AM
Hey @Nathan Bedell, Here it's implemented for
Effect
, https://github.com/arrow-kt/arrow/blob/main/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/nullable.kt.
Curious what your custom modified version is supposed to do? Also note that with context receivers, you don't need this extra boilerplate, and you could do something like this instead.
typealias Null = Nothing?

context(EffectScope<Null>)
@OptIn(ExperimentalContracts::class)
public suspend fun <B> B?.bind(): B {
    contract { returns() implies (this@bind != null) }
    return this ?: shift(null)
  }

suspend fun main() {
  val example: String? = null

  effect<Null, String> {
     example.bind()
  }.orNull()
}
y

Youssef Shoaib [MOD]

07/27/2022, 8:59 AM
@simon.vergauwen speaking of which actually, any plans for Arrow to utilise context receivers in the nearby future? Perhaps in a separate artifact or something?
s

simon.vergauwen

07/27/2022, 9:04 AM
Yes, ideally we deprecate these more elaborate runtimes and custom types in favor of simple context receiver DSLs but we are blocked by the Kotlin compiler.. It's currently only available for JVM, and only experimental if you enable the compiler flag 😅 So even in a separate artefact it's only possible for JVM atm.
On that note, I want to start designing and planning Arrow 2.0. I created a first ticket here, https://github.com/arrow-kt/arrow/issues/2768 And some discussions have taken place already during the bi-weekly public Arrow meetings. (You can poke #arrow-contributors if you want an invite to those meetings, non-obligatory to join every 2 weeks). I dumped some of my thoughts here, https://github.com/nomisRev/kotlin-gists You can check some thoughts surrounding flattening Validated/Either and removing some other types and APIs here, https://github.com/nomisRev/kotlin-gists/blob/main/src/main/kotlin/arrow2/Either.kt And 2 new implementations for Schedule without emulating dependent types, https://github.com/nomisRev/kotlin-gists/blob/main/src/main/kotlin/Schedule.kt https://github.com/nomisRev/kotlin-gists/blob/main/src/main/kotlin/Sched3.kt
y

Youssef Shoaib [MOD]

07/27/2022, 9:33 AM
Ooooooo exciting! I don't wanna overload this thread, but I btw almost have a complete implementation for a value class version of Option that (almost never) boxes. I'm gonna make a PR probably today or something, just figuring out some details around Effect and EagerEffect. (More details on that later but it turns out preventing boxing of a nested Option is a bit more complicated than it seems at first sight, but I was able to work around that). But yeah hopefully that could potentially make it into Arrow 2.0 if deemed useful
s

simon.vergauwen

07/27/2022, 9:40 AM
Yes, that'd be great to discuss for Arrow 2.0. Looking forward to see your findings
s

stojan

07/27/2022, 11:25 AM
This file experiments with an
Either
implementation that exposes an API covering both Either and Either use-cases.
I guess it's a typo, Validated and Either
s

simon.vergauwen

07/27/2022, 11:47 AM
Yes, it is 😅
@stojan & @Youssef Shoaib [MOD] let's discuss further in #arrow-contributors if you have any feedback. To not pollute this thread any further. @Nathan Bedell can you let me know if the provided info above was sufficient to solve your doubts/issues? 🙏
n

Nathan Bedell

07/27/2022, 11:47 PM
@simon.vergauwen Thanks for the link. It's basically a new approach to defining a monad comprehension syntax for "Tools" in my Iodine library. I'm coming back to it after awhile and I have a few ideas of how to simplify/improve things. Basically a tool is an async function that can manipulate the UI (think a modal dialog) -- but to thread it all together in compose the API needs more to it than just a raw async function. Tools also have a notion of cancellation, hence the being a variant of the nullable syntax.
@simon.vergauwen Glancing over that code, I think that should be sufficient, but I'll let you know if I have any questions.
Also @simon.vergauwen, re: "without emulating dependent types" -- what's that about? I've messed around a bit with a HKT-like encoding of (limited) type level functions in Kotlin (I can cook up a gist of you'd like to see), so I'm curious if this emulation of dependent types alluded to here is similar.
s

simon.vergauwen

07/28/2022, 7:18 AM
Warning… it’s super ugly 😅
Schedule
has a dependent type
State
, but you don’t want to expose it from the
Schedule<Input, Output>
type because it is only related to the internal impl of a
Schedule
. So you have to split the public type, and the “implementation type”. https://github.com/arrow-kt/arrow/blob/005c417fcad6831cf44503cfd35d3672d9b1302f/ar[…]oroutines/src/commonMain/kotlin/arrow/fx/coroutines/Schedule.kt Then you can expose a synthetic constructor that allows for specifying the “dependent type” without exposing it from the
Schedule<Input, Output>
type. https://github.com/arrow-kt/arrow/blob/005c417fcad6831cf44503cfd35d3672d9b1302f/ar[…]oroutines/src/commonMain/kotlin/arrow/fx/coroutines/Schedule.kt It’s rather ugly, and I wouldn’t advise on using such patterns in Kotlin. The same can typically be achieved by leveraging different techniques, as done in the linked alternative encodings for
Schedule
. Which results in much nicer, and simpler code.
If you have any questions or doubts on how to implement the DSLs for the Iodine library I’d be happy to help 👍
View count: 5