MarioAriasC / funKTionale

Functional constructs for Kotlin
915 stars 71 forks source link

Improve Either #18

Closed asm0dey closed 6 years ago

asm0dey commented 7 years ago
sealed class Either<out L : Any?, out R : Any?>(protected open val l: L?, protected open val r: R?) {

    class Left<out L : Any>(override val l: L) : Either<L, Nothing>(l, null) {
        override fun <T1 : Any, T2 : Any> map(ifLeft: ((L) -> T1)?, ifRight: ((Nothing) -> T2)?) = Left(ifLeft!!.invoke(l))
        override fun swap() = Right(l)
        override fun <T> case(left: ((L) -> T)?, right: ((Nothing) -> T)?) = left!!.invoke(l)
        override fun <C> case(left: C, right: C) = left
        override fun toString() = "Left: $l"
        override fun equals(other: Any?) = this === other || (other is Left<*> && l == other.l)
        override fun hashCode() = l.hashCode()
    }

    class Right<out R : Any>(override val r: R) : Either<Nothing, R>(null, r) {
        override fun <T1 : Any, T2 : Any> map(ifLeft: ((Nothing) -> T1)?, ifRight: ((R) -> T2)?) = Right(ifRight!!.invoke(r))
        override fun swap() = Left(r)
        override fun <T> case(left: ((Nothing) -> T)?, right: ((R) -> T)?) = right!!.invoke(r)
        override fun <C> case(left: C, right: C) = right
        override fun toString() = "Right: $r"
        override fun equals(other: Any?) = this === other || (other is Right<*> && r == other.r)
        override fun hashCode() = r.hashCode()
    }

    fun isLeft() = l !== null
    fun isRight() = r !== null
    fun left() = l!!
    fun right() = r!!
    abstract fun <C> case(left: C, right: C): C
    abstract fun <T> case(left: ((L) -> T)?, right: ((R) -> T)?): T
    abstract fun <T1 : Any, T2 : Any> map(ifLeft: ((L) -> T1)?, ifRight: ((R) -> T2)?): Either<T1, T2>
    abstract fun swap(): Either<R, L>
}

That's much easier to read and use