@optics
sealed interface LoadingContentOrError<out Data> {
data object Loading : LoadingContentOrError<Nothing>
@optics
sealed interface ContentOrError<out Data> : LoadingContentOrError<Data> {
companion object
}
@optics
data class Content<out Data>(val data: Data) : ContentOrError<Data> {
companion object
}
@optics
data class Error(val error: Throwable) : ContentOrError<Nothing> {
companion object
}
companion object
}
(We needed a type that represented only Content or Error, but not Loading, whilst still being a LoadingContentOrError.)
However, unfortunately, @optics isn't too happy about the generic usage here, either, and gives generates the following code:
inline fun <Data> LoadingContentOrError.Companion.contentOrError(): Prism<LoadingContentOrError<Data>, LoadingContentOrError.ContentOrError> = Prism(
getOrModify = { loadingContentOrError: LoadingContentOrError<Data> ->
when (loadingContentOrError) {
is LoadingContentOrError.ContentOrError -> loadingContentOrError.right()
else -> loadingContentOrError.left()
}
},
reverseGet = ::identity
)
inline fun <S,Data> Iso<S, LoadingContentOrError<Data>>.contentOrError(): Prism<S, LoadingContentOrError.ContentOrError> = this + LoadingContentOrError.contentOrError()
inline fun <S,Data> Lens<S, LoadingContentOrError<Data>>.contentOrError(): Optional<S, LoadingContentOrError.ContentOrError> = this + LoadingContentOrError.contentOrError()
inline fun <S,Data> Optional<S, LoadingContentOrError<Data>>.contentOrError(): Optional<S, LoadingContentOrError.ContentOrError> = this + LoadingContentOrError.contentOrError()
inline fun <S,Data> Prism<S, LoadingContentOrError<Data>>.contentOrError(): Prism<S, LoadingContentOrError.ContentOrError> = this + LoadingContentOrError.contentOrError()
inline fun <S,Data> Setter<S, LoadingContentOrError<Data>>.contentOrError(): Setter<S, LoadingContentOrError.ContentOrError> = this + LoadingContentOrError.contentOrError()
inline fun <S,Data> Traversal<S, LoadingContentOrError<Data>>.contentOrError(): Traversal<S, LoadingContentOrError.ContentOrError> = this + LoadingContentOrError.contentOrError()
inline fun <S,Data> Fold<S, LoadingContentOrError<Data>>.contentOrError(): Fold<S, LoadingContentOrError.ContentOrError> = this + LoadingContentOrError.contentOrError()
inline fun <S,Data> Every<S, LoadingContentOrError<Data>>.contentOrError(): Every<S, LoadingContentOrError.ContentOrError> = this + LoadingContentOrError.contentOrError()
Here, it's missing the type parameter for LoadingContentOrError.ContentOrError, which should be LoadingContentOrError.ContentOrError<Data>, not just LoadingContentOrError.ContentOrError. The correctly generated code would look like this:
inline fun <Data> LoadingContentOrError.Companion.contentOrError(): Prism<LoadingContentOrError<Data>, LoadingContentOrError.ContentOrError<Data>> =
Prism(
getOrModify = { loadingContentOrError: LoadingContentOrError<Data> ->
when (loadingContentOrError) {
is LoadingContentOrError.ContentOrError -> loadingContentOrError.right()
else -> loadingContentOrError.left()
}
},
reverseGet = ::identity,
)
inline fun <S, Data> Iso<S, LoadingContentOrError<Data>>.contentOrError(): Prism<S, LoadingContentOrError.ContentOrError<Data>> = this + LoadingContentOrError.contentOrError()
inline fun <S, Data> Lens<S, LoadingContentOrError<Data>>.contentOrError(): Optional<S, LoadingContentOrError.ContentOrError<Data>> = this + LoadingContentOrError.contentOrError()
inline fun <S, Data> Optional<S, LoadingContentOrError<Data>>.contentOrError(): Optional<S, LoadingContentOrError.ContentOrError<Data>> = this + LoadingContentOrError.contentOrError()
inline fun <S, Data> Prism<S, LoadingContentOrError<Data>>.contentOrError(): Prism<S, LoadingContentOrError.ContentOrError<Data>> = this + LoadingContentOrError.contentOrError()
inline fun <S, Data> Setter<S, LoadingContentOrError<Data>>.contentOrError(): Setter<S, LoadingContentOrError.ContentOrError<Data>> = this + LoadingContentOrError.contentOrError()
inline fun <S, Data> Traversal<S, LoadingContentOrError<Data>>.contentOrError(): Traversal<S, LoadingContentOrError.ContentOrError<Data>> = this + LoadingContentOrError.contentOrError()
inline fun <S, Data> Fold<S, LoadingContentOrError<Data>>.contentOrError(): Fold<S, LoadingContentOrError.ContentOrError<Data>> = this + LoadingContentOrError.contentOrError()
inline fun <S, Data> Every<S, LoadingContentOrError<Data>>.contentOrError(): Every<S, LoadingContentOrError.ContentOrError<Data>> = this + LoadingContentOrError.contentOrError()
Thanks a lot for getting fixes out for https://github.com/arrow-kt/arrow/issues/3380 and https://github.com/arrow-kt/arrow/issues/3381 so fast in version 1.2.3! Now that we're able to start playing around with the
Raise
DSL, we've discovered another snippet of code that generates bad Kotlin code from Optics. (I'm sorry-not-sorry for doing this!)Inspired by https://arrow-kt.io/learn/typed-errors/own-error-types/, we did something like this:
(We needed a type that represented only
Content
orError
, but notLoading
, whilst still being aLoadingContentOrError
.)However, unfortunately,
@optics
isn't too happy about the generic usage here, either, and gives generates the following code:Here, it's missing the type parameter for
LoadingContentOrError.ContentOrError
, which should beLoadingContentOrError.ContentOrError<Data>
, not justLoadingContentOrError.ContentOrError
. The correctly generated code would look like this: