is there a typesafe way to do partial application ...
# announcements
b
is there a typesafe way to do partial application in kotlin? I’ve got a bunch of objects with a run method that receives a variable amount of different parameters and I need to make it fit an interface which takes only one common parameter. Not super keen on creating a factory class per object.
b
yep, but I’ve got different types as well
basically: run(common: Common, value1: String) and run(common: Common, value1: Int, value2: URI)
I want to make them fit an interface that requires run(common: Common)
ideally I could do something like:
val x: CommonRun = obj1.run.apply("hi")
val y: CommonRun = obj2.run.apply(3, URI("<https://google.com>"))
I’d need to move the common stuff at the end ofc
I could ofc do:
Copy code
val x = CommonRun { obj1.run(it, "hi") }
but that’s a bit clunky
n
Why's that clunky? Seems reasonably concise and nicely explicit to me
n
i’m afraid that you’d need a dynamically-typed language in kotlin, you’d pass an vararg of
Any
and you need to cast in subclasses 🤷‍♂️
passing a lambda is a nice trick 👍
k
I’m not exactly sure of what you are trying to achieve, but you could experiment with extension functions. This would allow your interface to only have a single method and to still elegantly support all cases in a type safe manner.
Copy code
fun Common.run(value: Int): CommonRun = TODO()
b
I need a way to bind the additional parameters in code though, not sure how an extension function would help
k
Well, you would pass them and capture them somehow in your extension function. I have too little information to give you an exact example.
n
You don't need a dynamically typed language, but you do probably need variadics to do this properly
youcould do this in C++, but it's pretty painful
In Kotlin, you'd have to write overloads for apply in both the ari-ness of the passed function, and in the position of common
Copy code
fun<T, R> apply(fun: (T, Common) -> R, t: T) = { fun(t, it) }
fun<T, R> apply(fun: (Common, T) -> R, t: T) = { fun(it, t) }

fun<T, U, R> apply(fun: (Common, T, U) -> R, t: T, u: U) = { fun(it, t, u) }
fun<T, U, R> apply(fun: (T, Common, U) -> R, t: T, u: U) = { fun(t, it, u) }
fun<T, U, R> apply(fun: (T, U, Common) -> R, t: T, u: U) = { fun(t, u, it) }
...
i think something like that should work but it's a bit horrible
but this probably has edge cases and such, I think it's a lot better to just do the same thing at the call site, as you had before (the code you called "clunky")