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
  • e

    EarthCitizen

    01/08/2020, 7:45 PM
    I am confused as to why
    Either.catch()
    requires a suspend function
    r
    • 2
    • 14
  • a

    Attila Domokos

    01/08/2020, 9:47 PM
    I've started playing with Monad transformers with Arrow recently. This is a function I came up with: https://github.com/adomokos/explorer-kt/blob/master/src/main/kotlin/explorer/CsvUserImporter.kt#L36-L51 The line
    EitherT.monad<ForIO, AppError>(IO.monad()).fx.monad {
    looks a bit scary. Is there a simpler way to express this?
    j
    • 2
    • 6
  • e

    EarthCitizen

    01/09/2020, 6:57 AM
    Dealing with
    Either.catch()
    being a suspend has turned out to be quite a pain …why is it unsafe to make my own
    catch()
    function that is not a suspend version? …as in what problem will I run into …keep in mind that I am not using coroutines in the code in question …I have a large number of functions that wrap other functions to return their exceptions as a
    Left
    . My code is getting quite ugly as I am having to weave a lot of
    runBlocking { }
    into my call stacks …namely inside of
    flatMap { }
    and
    handleErrorWith { }
    p
    • 2
    • 1
  • j

    Jorge Castillo

    01/09/2020, 8:10 AM
    That's a bit outdated but most of the patterns there still apply. I'd ignore Try, since it's recommended to use Either.catch or IO instead. Read this post for more details on that https://jorgecastillo.dev/please-try-to-use-io
    👍 1
    ❤️ 1
    m
    s
    • 3
    • 12
  • g

    Gopal S Akshintala

    01/09/2020, 5:57 PM
    I see
    arm(ME: MonadError<F, NukeException>)
    and
    aim(ME: MonadError<F, NukeException>)
    are taking input params, but in the subsequent code those functions don’t have params while invoking
    fun <F> MonadError<F, NukeException>.attack():Kind<F, Impacted> =
      fx.monad {
        val (nuke) = arm<F>()
        val (target) = aim<F>()
        val (impact) = launch<F>(target, nuke)
        impact
      }
    j
    r
    • 3
    • 2
  • k

    kyleg

    01/09/2020, 6:15 PM
    Why is it that
    val x: Option<Any> = TODO()
    fun y: IO<Any> = TODO()
    
    IO.fx {
       x.fold({}, { y.bind() })
    }
    is OK, but
    val x: Option<Any> = TODO()
    fun y: IO<Any> = TODO()
    
    IO.fx {
       x.map { y.bind() }
    }
    is not (the latter complains about
    bind
    needing to be running in a co-routine? What’s the design decision backing this? Just curious because I have a fn returning an
    Option
    , and if it is
    None
    I don’t need to do anything. Only if it’s
    Some
    . I almost re-wrote some code when I initially tried
    map
    and it gave me this error. Fortunately I tried
    fold
    to see if it would work. Of course, it’s more verbose because of the empty lambda for
    isEmpty
    . If I can understand the justification for this, it’ll likely help me avoid problems in the future.
    j
    i
    r
    • 4
    • 27
  • p

    pakoito

    01/09/2020, 8:50 PM
    what you’d like is something like a couple of MVars that you update with the latest value, that you combine with
    Applicative.map
    into an Either or an Option
    👍 1
    m
    j
    • 3
    • 16
  • e

    EarthCitizen

    01/10/2020, 10:01 AM
    Why can’t I call
    Either.catch()
    from inside
    Either.fx { }
    ? …I see an error about restricted suspending functions, but I don’t understand how to see what can be called from within
    Either.fx { }
    …I am currently getting around the problem by doing this, but I don’t know if it is safe to do:
    fun <L, R> Either.Companion.catchSafely(
        mapper: (Throwable) -> L,
        block: () -> R): Either<L, R> =
        runBlocking {
            catch(
                suspend  { block() }
            )
        }.mapLeft(mapper)
    r
    • 2
    • 4
  • p

    pakoito

    01/10/2020, 4:25 PM
    same for me, I know some basics of CT, and got more mileage from applying them in examples and projects such as porting papers to Arrow
    s
    r
    • 3
    • 5
  • a

    Attila Domokos

    01/10/2020, 11:31 PM
    I might have missed this in the docs somewhere, but when I use
    IO
    to model effects, do I need to use
    suspend
    on the functions as well? I am looking at examples here (https://jorgecastillo.dev/kotlin-fp-2-monad-transformers) and I don't see it at all. When do I need to use
    suspend
    ?
    👍 1
    m
    • 2
    • 1
  • p

    pakoito

    01/10/2020, 11:36 PM
    this may help you understand 😄
    a
    • 2
    • 2
  • a

    Attila Domokos

    01/10/2020, 11:59 PM
    It would be great if you had a small GitHub repo, where people could try out the code that you cover in your posts on their computers. Maybe a single GH repo with different packages based on the articles coud work. Advanced articles and examples on Arrow (like Monad Transformers) are rare, I know I should contribute with more writing as well.
    👍🏾 2
    p
    • 2
    • 4
  • p

    pakoito

    01/11/2020, 12:03 AM
    it’s a time thing mostly. I could squeeze the article in a couple of flights/train rides; a whole repo is another story for now
    a
    j
    • 3
    • 14
  • m

    mmaillot

    01/12/2020, 11:56 AM
    What is the best approach to handle this case:
    loadURL().flatMap { url -> callWS(url) }.flatMap { saveResulte(url: ???, response: it) }
    How can I get the url to save it in the last flatMap ? Should I use a pair in the second flatmap
    .flatMap { url -> callWS(url).map { Pair(it, url) } }
    ?
    j
    s
    • 3
    • 9
  • m

    matiaslev

    01/13/2020, 4:55 PM
    Hi! I'm having a lot of fun learning with this post: https://www.47deg.com/blog/conway-swift/ Many thanks to @tomasruizlopez for that! 🎉 As a result of my learning, I carried the code from bow to arrow. Here is the repository https://github.com/matiaslev/ArrowLifeGameComonads. PS: If I do an Android project, I don't see the code generated for the type classes. If someone can help me it would be great. I hope it is useful for another person. Thanks!
    🏹 5
    👏 4
    🍎 3
    :arrow: 5
    p
    j
    +2
    • 5
    • 28
  • a

    Attila Domokos

    01/13/2020, 7:05 PM
    How can I run IO functions in this lambda? I'd like to get the commented out code to work: https://github.com/adomokos/kotlin-sandbox/blob/master/src/test/kotlin/sandbox/arrow/ReaderSpec.kt#L107-L116
    j
    • 2
    • 5
  • j

    julian

    01/13/2020, 7:35 PM
    I found this in a blog post:
    In a 
    Monad
     the 
    unit
     function takes a pure value, and wraps it in an 
    F
     structure 
    F[A]
    Is this use of the word
    pure
    related to its use in the term
    pure function
    ? If so, how?
    j
    • 2
    • 9
  • r

    rcd27

    01/14/2020, 10:14 AM
    Hi guys, looking for some
    arrow
    talk wich is about "abstracting over implementations". What I mean: moving such decisions like "which Async implementation I want to use this time: RxJava or Coroutines" to one place. I remember there was something about it, but can't find which one.
    s
    m
    • 3
    • 4
  • k

    kyleg

    01/15/2020, 1:05 AM
    I’m having an issue/confusion with
    fix()
    . I thought it converted
    Kind<F, A>
    into
    F<A>
    , where (for example)
    F
    is
    Option
    . But then I have this, and the compiler disagrees that my type is correct:
    import arrow.core.Either
    import arrow.core.Option
    import arrow.core.extensions.option.traverse.traverse
    import arrow.core.k
    import <http://arrow.fx.IO|arrow.fx.IO>
    import arrow.fx.extensions.fx
    import <http://arrow.fx.extensions.io|arrow.fx.extensions.io>.applicative.applicative
    import arrow.fx.fix
    import <http://java.io|java.io>.File
    
    interface MediaId
    interface Entity
    interface Foo { val source: Option<File> }
    val pathArgs: Foo = TODO()
    fun bar(x: String): IO<Sequence<File>> = TODO()
    fun transform(it: File): Entity = TODO()
    fun baz(x: Entity): IO<Either<Throwable, MediaId>> = TODO()
    
    
    val result: IO<Option<Sequence<Either<Throwable, MediaId>>>> = pathArgs.source.traverse(IO.applicative()) {
        IO.fx {
            val files = bar(it.canonicalPath).bind()
            files.k().traverse(IO.applicative()) {
                val entity = transform(it)
                baz(entity)
            }.fix().bind()
        }
    }.fix() // IO<Kind<ForOption, SequenceK<Either<Throwable, MediaId>>>> ???
    The
    fix()
    at the end does turn it from
    Kind<IO, …>
    into
    IO<…
    but why doesn’t the
    fix()
    tagged onto the internal
    traverse
    not turn the
    Kind<ForOption, SequenceK
    into
    Option<SequenceK>
    ?
    j
    • 2
    • 1
  • r

    rcd27

    01/15/2020, 9:05 AM
    Waaaait a minute. Learning Scala at the moment, after 3 years of Kotlin + interest and contributing in
    Arrow
    . "I've seen this all already somewhere" 🤔
    s
    e
    m
    • 4
    • 17
  • s

    Sagar Suri

    01/15/2020, 9:49 AM
    Two quick questions: 1) Where can I read about how Arrow optics compute over immutable data objects ? 2) what is the downside of using Reader monad for DI in comparison to framework like Dagger?
    s
    a
    +3
    • 6
    • 18
  • g

    Gopal S Akshintala

    01/15/2020, 10:34 AM
    For the other one, it is done through inheritance
    interface FetcherDependencies<F>: MonadThrow<F> {
    
      fun api(): ApiService
    
      companion object {
        operator fun invoke(ME: MonadThrow<F>, api: ApiService): FetcherDependencies =
          object: FetcherDependencies, MonadThrow<F> by ME {
            override fun api() = api
          }
      }
    }
    e
    • 2
    • 3
  • c

    CLOVIS

    01/16/2020, 7:51 AM
    If I understand correctly, Kind<A, B> is just a Kotlin-friendly way of saying A<B>, right?
    s
    • 2
    • 11
  • s

    simon.vergauwen

    01/16/2020, 9:07 AM
    All build with functional APIs so it’s mostly simple DSLs that return composable types 🎉
    r
    • 2
    • 1
  • b

    Bruno

    01/16/2020, 10:40 AM
    Hey guys, awesome new site arrow-kt.io! Really beautiful, I'm stunned.
    k
    • 2
    • 1
  • b

    Bruno

    01/16/2020, 10:41 AM
    Beginner question: I am trying to copy the haskell interact function: interact :: (String -> String) -> IO () The 
    interact
     function takes a function of type 
    String->String
     as its argument. The entire input from the standard input device is passed to this function as its argument, and the resulting string is output on the standard output device. I got something like:
    fun interact(f: (String) -> String): IO<Unit> = IO.fx {
        f.apply { readLine() }
    }
    but now I am unsure how to proceed.
    j
    e
    p
    • 4
    • 28
  • b

    Bob Glamm

    01/16/2020, 1:58 PM
    @pakoito Maybe that answer (and
    Either.catch {}
    ) should make it into the channel topic description? 😄
    😂 1
    p
    a
    • 3
    • 5
  • j

    Jannis

    01/16/2020, 2:05 PM
    The docs should get a github link to most if not all pages (autogenerated if possible) that straight leads to an edit link for that page. Named "Edit this document" or something. Would make contributing to the docs much easier ^^ Not sure how easy that is with all the autogenerated docs we have...
    r
    • 2
    • 1
  • p

    PhBastiani

    01/16/2020, 3:41 PM
    @Egor Trutenko months ago i played with Free... And, i wrote this 2 GIST https://gist.github.com/PhBastiani/26d8734ff33001cb0304df337ea936a1 https://gist.github.com/PhBastiani/a68dadf73da3050f9e4e46fbe981f6da Thx to @Jannis pointed me out a type safe solution using a simple ADT... Feedback are wellcome
    r
    e
    j
    • 4
    • 10
  • k

    kyleg

    01/17/2020, 3:46 AM
    Based on my understanding, in CLEAN architecture, a use case is essentially a class you pass setup stuff to (like repository, etc.) and then later you’ll pass params to it to get some meaningful info. For example
    class UseCase(private val repository: MyDatabase) {
        operator fun invoke(file: File): Long { repository.getSomeLong() }
    }
    
    fun test() {
        val repo: MyDatabase = TODO()
        val useCase = UseCase(repo)
        // some hundreds of lines later
        useCase(File("/path/to/foo"))
    }
    I haven’t used
    State
    yet, but the descriptions I see largely seem like it’s somewhat similar in concept. You create an object with parameters representing things you’ll read/write to (like a repository) and later do something with it like DB insertions, retrievals, all to manage app state or something? Is my understanding correct?
    c
    j
    a
    • 4
    • 14
Powered by Linen
Title
k

kyleg

01/17/2020, 3:46 AM
Based on my understanding, in CLEAN architecture, a use case is essentially a class you pass setup stuff to (like repository, etc.) and then later you’ll pass params to it to get some meaningful info. For example
class UseCase(private val repository: MyDatabase) {
    operator fun invoke(file: File): Long { repository.getSomeLong() }
}

fun test() {
    val repo: MyDatabase = TODO()
    val useCase = UseCase(repo)
    // some hundreds of lines later
    useCase(File("/path/to/foo"))
}
I haven’t used
State
yet, but the descriptions I see largely seem like it’s somewhat similar in concept. You create an object with parameters representing things you’ll read/write to (like a repository) and later do something with it like DB insertions, retrievals, all to manage app state or something? Is my understanding correct?
c

Christian Maus

01/17/2020, 10:38 AM
I understand the state monad as a replacement for mutable state. For injection of dependencies (like a repository) the reader monad seems like a appropriate abstraction. Just my opinion (kind of FP newbie myself)
👍 2
j

Jannis

01/17/2020, 10:54 AM
@Christian Maus that is correct. "Dependency injection" with the reader monad is very common in the fp world, In the haskell world this is called the
ReaderT
pattern,
ZIO
(from scala) has a version of this built in in their
IO
monad. First of: a reader is a wrapper around a partially applied function:
Reader<R, A> = (R) -> A
and the transformer version
ReaderT<F, R, A> = (R) -> Kind<F, A>
. This means this pattern is no different from the code example @kyleg posted. The benefits are: typeclass instances (it is a monad (and a few other things), which means you can also do
fx
comprehensions over it) Second: Using a reader in arrow depends on how you use arrow: If you use arrow fx, you should use
ReaderT<ForIO, R, A>
to make this pattern work well with
IO
. There is also plans to make this pattern in-built into
IO
because it is so common, so using this for now and refractoring to the inbuilt version later should be easy as they are isomorphic. If you don't use arrow fx using the normal
Reader
should work fine ^^ The
UseCase
class is technically no different from
Reader<MyDatabase, (File) -> Long>
. This is better modeled as
(File) -> Reader<MyDatabase, Long>
but those two work basically the same anyway. The benefit is, that it can be composed easily
👍 2
k

kyleg

01/18/2020, 1:15 AM
Hm, for some reason I thought that State was basically just a Reader and a Writer put together. I haven’t dug into any of the three yet but when I’d see tutorials, often they’d discuss all three in the same article. I guess since I knew a state was something you’d read and write, I assumed that that’s what it was, haha. Kind of like a ReadStream and WriteStream put together is aReadWriteStream
j

Jannis

01/18/2020, 2:12 AM
It is if you look at the representation for both:
ReaderT = (R) -> Kind<F, A>
,
WriterT = Kind<F, Tuple2<W, A>>
now lets compose them with `R == W`:
ReaderT<WriterTPartial<F, R>, R, A> == (R) -> WriterT<F, R, A> == (R) -> Kind<F, Tuple2<R, A>> == StateT<F, R, A>
. So in theory they are the same, but the semantics of
Writer
and
Reader
are different which means the composition of the two does not work in practice (mainly because the output from the writer is never fed into the reader, so we actually have no changeable state). They are only equal in representation 😅 They also all evolved from similar problems and they are the most fundamental monad-transformers out there (Their
Id
variants
ReaderT<ForId, *, *> == Reader<*, *>
are also really easy to explain). So anyway here are the problems which led to ppl using those types: • Constantly passing around parameters or partially applied functions for DI is solved by
Reader
turning
(A) -> B
into
Reader<A, B>
which allows the function to use the context, but doesn't force callers to provide it (they just need to return a
Reader<A, B>
like as well. • Constantly passing around accumulated logs, values etc is solved by
Writer
turning a function returning
(W, B)
into a function returning
Writer<W, B>
, this has the same benefits, but abstracts away the log. • Constantly passing around and feeding changed state is solved by
State
turning functions
(S) -> (S, A)
into
State<S, A>
again providing a nice abstraction.
❤️ 1
k

kyleg

01/18/2020, 3:55 AM
Dammit @Jannis you are too helpful and kind
❤️ 1
a

aballano

01/18/2020, 11:55 PM
@Jannis great explanation 👏 if you would like to do something similar over IO, would it be possible to use Kleisli there?
j

Jannis

01/19/2020, 12:14 AM
Do you mean using a
Reader
in
IO
context? In that case
Kleisli<ForIO, R, A>
will do just fine.
ReaderT
is also just a typealias for
Kleisli
anyway.
👌 1
k

kyleg

01/19/2020, 12:25 AM
So I dived straight into refactoring my code to learn about readers, and it seems that for anything of type
Reader<A, B>
created with
Reader { context -> returnsB() }
I have to add on
.run { Id(this) }
at the end. Same goes for
ReaderApi.ask<A>().map context -> returnsB() }
Did Arrow change the API for this? Because looking at this sample project using Arrow Reader, they don’t appear to have had to do this. He actually imports Reader from
arrow.data
but I have to import it from
arrow.mtl
as it does not appear to exist in
arrow-data
module anymore.
For instance,
typealias AppReader<T> = Reader<AppContext, T>

fun scanVideo(root: String): AppReader<IO<Sequence<File>>> = Reader { ctx ->
    Id(IO.effect { /*snip*/ })
}
By comparison, sample project https://github.com/leandroBorgesFerreira/ArrowTry/blob/master/app/src/main/java/br/com/leandro/arrowtry/githubrepos/data/RepositoriesDataSource.kt
j

Jannis

01/19/2020, 12:42 AM
Yes that is quite outdated.
Reader
is an alias for
ReaderT<ForId, R, A>
which is an alias for
Kleisli<ForId, R, A>
(for category theory reasons I think). So using the constructor invokes the
Kleisli
constructor which is
f: (R) -> Kind<F, A>
. The easiest way to get into reader context is to use
ReaderApi
as in the linked repo. Then you can also skip the
Id(...)
ReaderApi.ask<A>().map { context -> returnsB() }
If
returnsB
returns
Reader<A, *>
(given that
context
has type
A
here) what you want would be
ReaderApi.ask<A>().flatMap { ctx -> returnsB() }
. You could also do fx:
Reader.monad(Id.monad()).fx.monad { // Not sure if there is a shorthand somewhere, so I'll fully qualify it... You may also need more type params
  val cts = ReaderApi.ask<A>().bind()
  ...
  returnsB().bind()
}
Yes that is quite outdated
Although mtl hasn't changed too much in recent versions, so while stuff got moved, fx and some typeclasses changed, the functions from mtl are still similar, if not the same
k

kyleg

01/19/2020, 1:03 AM
I think what was throwing me was that I’m running 10.4 but I still have to manually tag
.andThen { Id(it) }
on the end of my
Reader { … }
constructors. It doesn’t appear to be making use of the
Reader(run: …) = ReaderT(run.andThen(Id(it)})
code that Arrow has. I need to figure out why that is.
j

Jannis

01/19/2020, 1:13 AM
Oh right that exists ^^. That is indeed confusing. I haven't used the non-transformer variants enough...
View count: 10