Another question that I have. What is the recommen...
# arrow
c
Another question that I have. What is the recommended way of doing dependency injection ? Based on my research, there is the Reader monad based on a article written by Jorge Castillo. There is also this

talk▾

with Francisco Garcia. And also in the arrow documentation, you can do it using Typeclass. What is the recommended way of doing dependency injection ? what are the advantages of one method over the other ? If this question is not asked to the right channel, feel free to redirect me to the correct one
p
Reader is a more general technique that comes with a runtime cost, and some boilerplate. The other one takes extension functions and makes them into DI elements. It takes a bit more brainpower to get right, and comes without a runtime penalty. Both approaches are purely functional. You still have the global injector frameworks like coin and dagger, depending on how much magic and coupling you'd like in your app.
s
here is one approach with Extension functions in a gist by @raulraja https://gist.github.com/raulraja/97e2d5bf60e9d96680cf1fddcc90ee67
s
@pakoito what is the runtime cost for reader ?
p
You're wrapping and unwrapping into a Reader, even if you have no effects or...either, it'll be
Id
, which is just regular boxing.
Copy code
fun Int.thing(): Int = this

fun thing(): Reader<Int, Int> = Reader {
  ask()
}
s
Right. That I’ve notice a lot while using reader.
s
https://gist.github.com/nomisRev/1f91710ebec1709d4ce8059812482624 Here is another example which uses extensions functions to replace
Reader
, interface delegation to do dependency composition, and uses generic function constraints to define top-level function that can define all there dependencies as non-params.
c
Ok thx for your useful responses
h
The only limitation I've found using the extension functions solution is with anonymous suspend functions. Or maybe I'm not aware of how to declare them...
Copy code
fun <R : Console> doSomething() {
  val myFunction: suspend R.(i: Int) -> Unit = suspend { i: Int -> print("AAA $i") }
(this doesn't compile)
(sorry, I was wrong, it can be defined without problems...)
p
¿?
what was the issue?
h
probably that I was too tired... 🤣 anyway, in the past I had some compatibility problems, e.g with List<>.traverse(). I can traverse a List<IO<A>> but not a List<suspend () -> A>, but maybe now it is fixed.
s
but not a List<suspend () -> A>, but maybe now it is fixed.
You can now 😉
🎉 1