I've created a function which is polymorphic in the Monad it needs to use, instead it depends on the typeclass instances that exists for this Monad. It looks like this:
fun <M> M.logic(...): Kind<M, String>
where M: MonadReader<M, Dependency>,
M: Effect<M> =
fx.monad() {
val dependency = ask().bind()
val response = effect { ...using dependency here... }.bind()
response
}
I'm using the MonadReader
to get a dependency, and I'm using Effect
, well, for effects. Now I assumed, that all I need is to use some Monad Transformers to get to this constellation of a Monad "at the end of the world" (i.e. in main()
). Something like ReaderT<ForIO, Dependency, Unit>
.
However, I can't seem to create a suitable M
(or any context) to call this method on. How can I call this method on an exact monad that has the necessary typeclass instances?
This is the code snippet you're after:
fun <M, F> M.logic(): Kind<F, String>
where M: MonadReader<F, String>,
M: Async<F> =
fx.monad {
val dependency = ask().bind()
val response = effect { dependency }.bind()
response
}
object Transformer:
Async<KleisliPartialOf<ForIO, String>> by ReaderT.async(IO.effect()),
KleisliMonadReader<ForIO, String> by ReaderT.monadReader(IO.monad())
Note that Async
is what you're after, not the poorly named Effect
. And you need two generics, one for the composition and another for the content.
Transformer.run {
logic()
}
The Async instance for Reader was added on January 2020, and will be available on the next release, either 0.10.5 or 0.11.0: https://github.com/arrow-kt/arrow/commit/6aaae6998de612eb0eec948697f1c477649230be