Is it possible to use Kotlin's by-delegation with an existing class/object (i.e.Arrow's Either)?

huangapple go评论82阅读模式
英文:

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&lt;L,R&gt;(private var delegate: Either&lt;L,R&gt;) {
     internal operator fun getValue(thisRef: Any?, property: KProperty&lt;*&gt;): Either&lt;L,R&gt; {
        return delegate
    }

    internal operator fun setValue(thisRef: Any?, property: KProperty&lt;*&gt;, value: Either&lt;L,R&gt;) {
        delegate = value
    }
}

fun main(args: Array&lt;String&gt;) {
    val delegate: Either&lt;Exception, String&gt; = Right(&quot;howdy&quot;)
    val myeither: Either&lt;Exception, String&gt; by EitherWrapper(delegate)
    println(&quot;IsLeft(): ${myeither.isLeft()}&quot;)
    println(&quot;IsRight(): ${myeither.isRight()}&quot;)
}

答案1

得分: 2

以下是翻译好的部分:

所以,我认为我对我的查询有一个解决方案。以下代码将一个“Either”包装在一个新类型“Exceptional”中。这段代码是我想要构建的起点。最终,我将拥有类似以下的东西:

Is it possible to use Kotlin's by-delegation with an existing class/object (i.e.Arrow's Either)?

我可以在整个后端服务中传递此类型的实例并返回更精确的异常、错误或值。

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) }
}

运行结果:

Is it possible to use Kotlin's by-delegation with an existing class/object (i.e.Arrow's Either)?

英文:

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:

Is it possible to use Kotlin's by-delegation with an existing class/object (i.e.Arrow's Either)?

I can pass an instance of this type throughout my backend service and return a more precise exception, error, or value.

interface EitherMonad&lt;L, R&gt; {
    val either: Either&lt;L, R&gt;
}

class BaseEitherMonad&lt;L, R&gt;(
    override val either: Either&lt;L, R&gt;
) : EitherMonad&lt;L, R&gt;

class Exceptional&lt;R&gt;(
    private val delegate: EitherMonad&lt;Exception, R&gt;
) : EitherMonad&lt;Exception, R&gt; by delegate {}

fun main() {

    val delegateRight = BaseEitherMonad&lt;Exception, String&gt;(Either.Right(&quot;howdy&quot;))
    val exceptionalRight = Exceptional(delegateRight)
    println(&quot;IsLeft(): ${exceptionalRight.either.isLeft()}&quot;)
    println(&quot;IsRight(): ${exceptionalRight.either.isRight()}&quot;)
    exceptionalRight.either.fold({ throw it }, { println(&quot;Right: $it&quot;) })
    exceptionalRight.either.map { println(it) }

    val delegateLeft = BaseEitherMonad&lt;Exception, String&gt;(Either.Left(IllegalStateException(&quot;Boom!&quot;)))
    val exceptionalLeft = Exceptional(delegateLeft)
    println(&quot;IsLeft(): ${exceptionalLeft.either.isLeft()}&quot;)
    println(&quot;IsRight(): ${exceptionalLeft.either.isRight()}&quot;)
    exceptionalLeft.either.fold({ throw it }, { println(&quot;Right: $it&quot;) })
    exceptionalLeft.either.map { println(it) }
}

A Run:
Is it possible to use Kotlin's by-delegation with an existing class/object (i.e.Arrow's Either)?

答案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&lt;T&gt;(private var delegate: T) {
  internal operator fun getValue(thisRef: Any?, property: KProperty&lt;*&gt;): T = 
    delegate

  internal operator fun setValue(thisRef: Any?, property: KProperty&lt;*&gt;, value: T) {
    delegate = value
  }
}

huangapple
  • 本文由 发表于 2020年7月30日 11:03:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/63165542.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定