英文:
Is it possible to use Kotlin's by-delegation with an existing class/object (i.e.Arrow's Either)?
问题
internal data class EitherWrapper<L, R>(private var delegate: Either<L, R>) {
internal operator fun getValue(thisRef: Any?, property: KProperty<*>): Either<L, R> {
return delegate
}
internal operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Either<L, R>) {
delegate = value
}
}
fun main(args: Array<String>) {
val delegate: Either<Exception, String> = Right("howdy")
val myeither: Either<Exception, String> by EitherWrapper(delegate)
println("IsLeft(): ${myeither.isLeft()}")
println("IsRight(): ${myeither.isRight()}")
}
英文:
I have a few specialized classes that I would like to create using Kotlin and Arrow and they will wrap around an Arrow Either monad. I've created the following code to use Kotlin's delegation, but I am wondering whether it can be simplified or made more idiomatic. Any suggestions would be appreciated.
Thank you for your time and interest.
internal data class EitherWrapper<L,R>(private var delegate: Either<L,R>) {
internal operator fun getValue(thisRef: Any?, property: KProperty<*>): Either<L,R> {
return delegate
}
internal operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Either<L,R>) {
delegate = value
}
}
fun main(args: Array<String>) {
val delegate: Either<Exception, String> = Right("howdy")
val myeither: Either<Exception, String> by EitherWrapper(delegate)
println("IsLeft(): ${myeither.isLeft()}")
println("IsRight(): ${myeither.isRight()}")
}
答案1
得分: 2
以下是翻译好的部分:
所以,我认为我对我的查询有一个解决方案。以下代码将一个“Either”包装在一个新类型“Exceptional”中。这段代码是我想要构建的起点。最终,我将拥有类似以下的东西:
我可以在整个后端服务中传递此类型的实例并返回更精确的异常、错误或值。
interface EitherMonad<L, R> {
val either: Either<L, R>
}
class BaseEitherMonad<L, R>(
override val either: Either<L, R>
) : EitherMonad<L, R>
class Exceptional<R>(
private val delegate: EitherMonad<Exception, R>
) : EitherMonad<Exception, R> by delegate {}
fun main() {
val delegateRight = BaseEitherMonad<Exception, String>(Either.Right("howdy"))
val exceptionalRight = Exceptional(delegateRight)
println("IsLeft(): ${exceptionalRight.either.isLeft()}")
println("IsRight(): ${exceptionalRight.either.isRight()}")
exceptionalRight.either.fold({ throw it }, { println("Right: $it") })
exceptionalRight.either.map { println(it) }
val delegateLeft = BaseEitherMonad<Exception, String>(Either.Left(IllegalStateException("Boom!")))
val exceptionalLeft = Exceptional(delegateLeft)
println("IsLeft(): ${exceptionalLeft.either.isLeft()}")
println("IsRight(): ${exceptionalLeft.either.isRight()}")
exceptionalLeft.either.fold({ throw it }, { println("Right: $it") })
exceptionalLeft.either.map { println(it) }
}
运行结果:
英文:
So, I think that I have a solution to my query. The following code wraps an Either within a new type: Exceptional. This code is the starting point for what I want to build. Eventually, I will have something like the following:
I can pass an instance of this type throughout my backend service and return a more precise exception, error, or value.
interface EitherMonad<L, R> {
val either: Either<L, R>
}
class BaseEitherMonad<L, R>(
override val either: Either<L, R>
) : EitherMonad<L, R>
class Exceptional<R>(
private val delegate: EitherMonad<Exception, R>
) : EitherMonad<Exception, R> by delegate {}
fun main() {
val delegateRight = BaseEitherMonad<Exception, String>(Either.Right("howdy"))
val exceptionalRight = Exceptional(delegateRight)
println("IsLeft(): ${exceptionalRight.either.isLeft()}")
println("IsRight(): ${exceptionalRight.either.isRight()}")
exceptionalRight.either.fold({ throw it }, { println("Right: $it") })
exceptionalRight.either.map { println(it) }
val delegateLeft = BaseEitherMonad<Exception, String>(Either.Left(IllegalStateException("Boom!")))
val exceptionalLeft = Exceptional(delegateLeft)
println("IsLeft(): ${exceptionalLeft.either.isLeft()}")
println("IsRight(): ${exceptionalLeft.either.isRight()}")
exceptionalLeft.either.fold({ throw it }, { println("Right: $it") })
exceptionalLeft.either.map { println(it) }
}
答案2
得分: 1
你的代码是正确的,唯一的改进之处,就我所见,是将其变得通用化,而不是特定于Either,如下所示:
internal data class DelegateWrapper<T>(private var delegate: T) {
internal operator fun getValue(thisRef: Any?, property: KProperty<*>): T =
delegate
internal operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
delegate = value
}
}
英文:
Your code is right and correct, the only improvement you could do, as far as I see, is to make it generic, and not Either-specific, as follows:
internal data class DelegateWrapper<T>(private var delegate: T) {
internal operator fun getValue(thisRef: Any?, property: KProperty<*>): T =
delegate
internal operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
delegate = value
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论