kotools / libraries

Multiplatform libraries for expressive programming with Kotlin.
https://kotools.github.io/libraries
MIT License
0 stars 0 forks source link

New number hierarchy #67

Closed LVMVRQUXL closed 1 year ago

LVMVRQUXL commented 1 year ago

Description

Introduce a new number hierarchy with the following types:

Existing types should inherit from the new ones for a seemless integration.

interface ExplicitNumber<out N : Number> {
    val value: N
}

interface NonZeroNumber<out N : Number> : ExplicitNumber<N> {}
interface PositiveNumber<out N : Number> : ExplicitNumber<N> {}
interface NegativeNumber<out N : Number> : ExplicitNumber<N> {}

interface StrictlyPositiveNumber<out N : Number> : NonZeroNumber<N>, PositiveNumber<N> {}
interface StrictlyNegativeNumber<out N : Number> : NonZeroNumber<N>, NegativeNumber<N> {}

Checklist

LVMVRQUXL commented 1 year ago

For flexibility purpose, we decided to give the minimum behaviour to the types: a function for building the type and overrides only. Other features will be implemented as extension functions.

LVMVRQUXL commented 1 year ago

This new hierarchy should have the following design (also available in this playground):

import kotlin.jvm.JvmInline
import kotlin.random.Random

// ---------- Number ----------

sealed interface ExplicitNumber<out N : Number> {
    val value: N
}

sealed interface NonZeroNumber<out N : Number> : ExplicitNumber<N>
sealed interface PositiveNumber<out N : Number> : ExplicitNumber<N>
sealed interface NegativeNumber<out N : Number> : ExplicitNumber<N>
sealed interface StrictlyPositiveNumber<out N : Number> : NonZeroNumber<N>, PositiveNumber<N>
sealed interface StrictlyNegativeNumber<out N : Number> : NonZeroNumber<N>, NegativeNumber<N>

// ---------- Int ----------

sealed interface ExplicitInt : ExplicitNumber<Int>

fun NonZeroInt(value: Int): Result<NonZeroInt> = NonZeroIntImplementation of value

sealed interface NonZeroInt : ExplicitInt, NonZeroNumber<Int> {
    object Exception : IllegalArgumentException("Given integer should be other than zero.")
}

@JvmInline
private value class NonZeroIntImplementation private constructor(override val value: Int) : NonZeroInt {
    override fun toString(): String = value.toString()

    internal companion object {
        internal infix fun of(value: Int): Result<NonZeroInt> = value.takeIf { it != 0 }
            ?.let(::NonZeroIntImplementation)
            ?.let { Result.success(it) }
            ?: Result.failure(NonZeroInt.Exception)
    }
}

sealed interface PositiveInt : ExplicitInt, PositiveNumber<Int>
sealed interface NegativeInt : ExplicitInt, NegativeNumber<Int>
sealed interface StrictlyPositiveInt : ExplicitInt, NonZeroInt, PositiveInt, StrictlyPositiveNumber<Int>
sealed interface StrictlyNegativeInt : ExplicitInt, NonZeroInt, NegativeInt, StrictlyNegativeNumber<Int>

fun main() {
    val x: NonZeroInt = Random.nextInt()
        .let(::NonZeroInt)
        .getOrThrow()
    println("x = $x")
    NonZeroInt(0)
        .getOrThrow()
}
LVMVRQUXL commented 1 year ago

Done.

LVMVRQUXL commented 1 year ago

We will finally try to represent all declarations related to numbers using only generics and the hierarchy of ExplicitNumber. The goal is to be able to do more with less types. For doing so, we now need to:

LVMVRQUXL commented 1 year ago

Done.

LVMVRQUXL commented 1 year ago

Introduce this new hierarchy as an alpha feature instead.

LVMVRQUXL commented 1 year ago

This new hierarchy will be designed with interfaces and extension functions instead of sealed interfaces and member functions for letting the ability to extend it without changing its behaviours.

LVMVRQUXL commented 1 year ago

Done.

LVMVRQUXL commented 1 year ago

We will revert the changes introduced by this issue, because the kotlin.Number type is not sealed and doesn't provide any operation for its children types, except explicit conversions. For Kotools Types 3.2, we will only focus on the explicit types for the kotlin.Int type.