hmm, I really don't like declaring something like this as an extension method on F: `fun <F> F...
b
hmm, I really don't like declaring something like this as an extension method on F:
fun <F> F.updateTimezone(ctx: DocumentContext): Kind<F, DocumentContext> where F: MonadThrow<F> { ... }
(with arrow 0.10.x), but IIRC I am waiting for Arrow 1.0 to have the equivalent of Scala's
(implicit MT: MonadThrow[F])
, right?
s
I typically define it on the typeclass itself
MonadThrow<F>
instead which allows me to use it within
fx.monadThrow { }
or use it on the receiver. By doing so you can also call these functions from each-other without having to pass the argument.
Copy code
fun <F> Async<F>.test(): Kind<F, Unit> = unit()
fun <F> Async<F>.helloWorld(): Kind<F, Unit> = effect { println("Hello World") }

fun <F> Async<F>.asyncProgram() = test().flatMap { helloWorld() }
But yes we’re all waiting for Arrow Meta to get rid of this completely 😅
b
That's what I had kind of guessed from reading the docs. I don't really like that pattern since it suggests that (e.g.)
helloWorld
is part of
Async<F>
, which just strikes me as weird
I can work around it for the time being by sticking all of the methods in a
class
, which is fine
s
Yes, I know it’s not a perfect solution. I’ve never thought about it that way tho, “suggests that (e.g.)
helloWorld
is part of `Async<F>`“. I’ve always thought about it as “the first param is implicitly passed, which allows calling it as syntax for the first argument. So where you typically do ``(implicit MT: MonadThrow[F])` ` as last argument in Scala, I do the same but as a receiver in Kotlin.
It’s just a compiler trick, and that’s how I’ve always reasoned about it. Here I want to create syntax for
Async<F>
, it has nothing to do for the type or class which just defines behavior for
F
.
b
Ahh, I think I understand your perspective. However, I do not think I could convince my coworkers to change their perception of class extension functions to that view
mentally, I find it the
implicit
function parameter easier to reason about, I guess: "This function requires some evidence that this typeclass instance exists for the given effect"
as opposed to "hey, I am adding some useful functionality to this type"
r
Extension functions are effectively implicits by import with a single argument
If they know Scala they may grasp that because it's also how Scala implicits are used to add syntax to types via implicit classes or implicit conversions