Skip to content

Instantly share code, notes, and snippets.

@Mahoney
Last active March 23, 2022 17:40
Show Gist options
  • Save Mahoney/26b9c884f919ffb18d6a57926ff11584 to your computer and use it in GitHub Desktop.
Save Mahoney/26b9c884f919ffb18d6a57926ff11584 to your computer and use it in GitHub Desktop.
Type safe integer behaviour in Kotlin
sealed interface Integer {
operator fun plus(other: Integer): Integer
operator fun plus(other: NonZeroInteger): Integer
operator fun plus(other: NonNegativeInteger): Integer
operator fun plus(other: NonPositiveInteger): Integer
operator fun plus(other: PositiveInteger): Integer
operator fun plus(other: NegativeInteger): Integer
operator fun plus(other: Zero): Integer
operator fun div(other: NonZeroInteger): Integer
operator fun div(other: PositiveInteger): Integer
operator fun div(other: NegativeInteger): Integer
val value: Int
companion object {
operator fun invoke(value: Int): Integer {
return if (value > 0) PositiveInteger(value)
else if (value < 0) NegativeInteger(value)
else Zero
}
}
}
sealed interface NonZeroInteger : Integer {
override operator fun plus(other: Integer): Integer
override operator fun plus(other: NonZeroInteger): Integer
override operator fun plus(other: NonNegativeInteger): Integer
override operator fun plus(other: NonPositiveInteger): Integer
override operator fun plus(other: PositiveInteger): Integer
override operator fun plus(other: NegativeInteger): Integer
override operator fun plus(other: Zero): NonZeroInteger
override operator fun div(other: NonZeroInteger): NonZeroInteger
override operator fun div(other: PositiveInteger): NonZeroInteger
override operator fun div(other: NegativeInteger): NonZeroInteger
companion object {
operator fun invoke(value: Int): NonZeroInteger {
return if (value > 0) PositiveInteger(value)
else if (value < 0) NegativeInteger(value)
else throw java.lang.IllegalArgumentException("NonZeroInteger cannot be 0")
}
}
}
sealed interface NonNegativeInteger : Integer {
override operator fun plus(other: Integer): Integer
override operator fun plus(other: NonZeroInteger): Integer
override operator fun plus(other: NonNegativeInteger): Integer
override operator fun plus(other: NonPositiveInteger): Integer
override operator fun plus(other: PositiveInteger): Integer
override operator fun plus(other: NegativeInteger): Integer
override operator fun plus(other: Zero): NonNegativeInteger
companion object {
operator fun invoke(value: Int): NonNegativeInteger {
return if (value > 0) PositiveInteger(value)
else if (value == 0) Zero
else throw java.lang.IllegalArgumentException("NonNegativeInteger cannot be $value")
}
}
}
sealed interface NonPositiveInteger : Integer {
override operator fun plus(other: Integer): Integer
override operator fun plus(other: NonZeroInteger): Integer
override operator fun plus(other: NonNegativeInteger): Integer
override operator fun plus(other: NonPositiveInteger): Integer
override operator fun plus(other: PositiveInteger): Integer
override operator fun plus(other: NegativeInteger): Integer
override operator fun plus(other: Zero): NonPositiveInteger
companion object {
operator fun invoke(value: Int): NonPositiveInteger {
return if (value < 0) NegativeInteger(value)
else if (value == 0) Zero
else throw java.lang.IllegalArgumentException("NonPositiveInteger cannot be $value")
}
}
}
@JvmInline
value class PositiveInteger(override val value: Int) : NonZeroInteger, NonNegativeInteger {
init {
require(value > 0)
}
override operator fun plus(other: Integer): Integer = Integer(value + other.value)
override operator fun plus(other: NonZeroInteger): Integer = Integer(value + other.value)
override operator fun plus(other: NonNegativeInteger): PositiveInteger = PositiveInteger(value + other.value)
override operator fun plus(other: NonPositiveInteger): Integer = Integer(value + other.value)
override operator fun plus(other: PositiveInteger): PositiveInteger = PositiveInteger(value + other.value)
override operator fun plus(other: NegativeInteger): Integer = Integer(value + other.value)
override operator fun plus(other: Zero): PositiveInteger = PositiveInteger(value + other.value)
override operator fun div(other: NonZeroInteger): NonZeroInteger = NonZeroInteger(value / other.value)
override operator fun div(other: PositiveInteger): PositiveInteger = PositiveInteger(value / other.value)
override operator fun div(other: NegativeInteger): NegativeInteger = NegativeInteger(value / other.value)
}
@JvmInline
value class NegativeInteger(override val value: Int) : NonZeroInteger, NonPositiveInteger {
init {
require(value < 0)
}
override operator fun plus(other: Integer): Integer = Integer(value + other.value)
override operator fun plus(other: NonZeroInteger): Integer = Integer(value + other.value)
override operator fun plus(other: NonNegativeInteger): Integer = Integer(value + other.value)
override operator fun plus(other: NonPositiveInteger): NegativeInteger = NegativeInteger(value + other.value)
override operator fun plus(other: PositiveInteger): Integer = Integer(value + other.value)
override operator fun plus(other: NegativeInteger): NegativeInteger = NegativeInteger(value + other.value)
override operator fun plus(other: Zero): NegativeInteger = NegativeInteger(value + other.value)
override operator fun div(other: NonZeroInteger): NonZeroInteger = NonZeroInteger(value / other.value)
override operator fun div(other: PositiveInteger): NegativeInteger = NegativeInteger(value / other.value)
override operator fun div(other: NegativeInteger): PositiveInteger = PositiveInteger(value / other.value)
}
object Zero : NonNegativeInteger, NonPositiveInteger {
override operator fun plus(other: Integer): Integer = other
override operator fun plus(other: NonZeroInteger): NonZeroInteger = other
override operator fun plus(other: NonNegativeInteger): NonNegativeInteger = other
override operator fun plus(other: NonPositiveInteger): NonPositiveInteger = other
override operator fun plus(other: PositiveInteger): PositiveInteger = other
override operator fun plus(other: NegativeInteger): NegativeInteger = other
override operator fun plus(other: Zero): Zero = other
override operator fun div(other: NonZeroInteger): Zero = Zero
override operator fun div(other: PositiveInteger): Zero = Zero
override operator fun div(other: NegativeInteger): Zero = Zero
override val value: Int = 0
override fun toString() = "Zero"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment