Mitchell Skaggs
06/05/2021, 8:25 AMGetter<S,A>
be contravariant on S
? I'm trying to use it in a contravariant way and it's not working in compositions. Having it contravariant in the original type would fix this.raulraja
06/05/2021, 8:38 AMS
is declared invariant in Getter<S, A>
because it defines members like zip where S
appears covariant as argument.
infix fun <C> zip(other: Getter<S, C>): Getter<S, Pair<A, C>>
I believe if we made Getter S
in
then we will have to defined all those members as extension instead so they can accept additional type args at the function level instead of receiving S
in the class scope. This causes people having to import manually all extensions. I believe this change would ripple through not just Getter but also fold and others in the hierarchy.
Do you have an example reduced code that shows your compilation error?Mitchell Skaggs
06/05/2021, 8:46 AMinterface MyInterface {
val myValue: String
}
// 2 or more subclasses
class Implentation1(override val myValue: String) : MyInterface
class Implentation2(override val myValue: String) : MyInterface
val getter = Getter<MyInterface, String> { it.myValue }
val myOtherLens: Lens<Unit, Implentation1> = TODO()
val composition = myOtherLens + getter // Error!
raulraja
06/05/2021, 9:00 AMFold
has S
as in
, results in `
val composition: Fold<Unit, String> = myOtherLens + getter
Changing Fold
S
to in
is something we can consider as it seems to not require to declare +
and others as extensions. Not sure if there are additional concerns so maybe we should get @simon.vergauwen and @Jannis opinion since they are more familiar with it.simon.vergauwen
06/05/2021, 9:14 AMMitchell Skaggs
06/05/2021, 9:28 AMsimon.vergauwen
06/05/2021, 9:31 AMMitchell Skaggs
06/05/2021, 9:38 AMinfix fun <C> compose(other: Getter<in A, C>): Getter<S, C> =
Getter(other::get compose this::get)
operator fun <C> plus(other: Getter<in A, C>): Getter<S, C> =
this compose other
This compiles and it resolves my issue.Jannis
06/05/2021, 9:41 AMUnsafeVariance
to silence the variance checker on method implementations to avoid having to use extensions @raulraja, bit annoying but should not be too much of a problem, kotlin itself uses it all over the place iirc.
Also use site variance such as what @Mitchell Skaggs suggested could work just fine. Iirc there are some annoying bits to it which is why I did not use it in my optics branch, but worth a try^^Jannis
06/05/2021, 9:44 AMcompose
thats available for all optics kinds^^raulraja
06/05/2021, 9:44 AMMitchell Skaggs
06/05/2021, 9:44 AMcompose
and plus
methods and it appears to work as described in https://github.com/optics-dev/Monocle/issues/770#issuecomment-737077273.
infix fun <C, D> compose(other: PIso<in A, out B, out C, in D>): PIso<S, T, C, D>
Mitchell Skaggs
06/05/2021, 9:45 AMcompose
variance changes into a PR in a simon.vergauwen
06/05/2021, 10:10 AMUnsafeVariance
to move the extension functions from Either to concrete methods, but failed. It caused some other issues.
Wow, didn't know we could use site variancee like this 😮 Is this a new feature? 🙃Mitchell Skaggs
06/05/2021, 10:22 AMMitchell Skaggs
06/06/2021, 4:04 AM