How to fix these tagged Ints?

I’m trying to define tagged Ints that are subtypes of Int. Below is my attempt:

import TInts.*

val three: TInt["tag"] = TInt["tag"](3)
val four: TInt["tag"] = TInt["tag"](4)
val seven: TInt["tag"] = three + four
// Compile-error:
//   Found:    Int
//   Required: TInt[("tag" : String)]

object TInts:
  opaque type TInt[+T] <: Int = Int

  object TInt:
    inline def apply[T](value: Int): TInt[T] = value

  extension [T](m: TInt[T])
    inline def +[I <: Int](n: I): TInt[T] | I = m + n

However, this code does not compile. How come the addition of three and four returns an Int, instead of a TInt?

I could be wrong, But I think is because since TInt <: Int then the + is the one from Int rather than the extension
Also not sure if the type of the extension is the correct.

1 Like

@BalmungSan Thanks! I think you’re right. So adding that subtyping relation is no good in this case.

Below is my revised code, which seems okay so far.

object TInts:
  opaque type TInt[+T] = Int

  object TInt:
    inline def apply[T](value: Int): TInt[T] = value
    given [T]: Conversion[TInt[T], Int] with
      def apply(n: TInt[T]): Int = n

  extension [T](m: TInt[T])
    inline def +[I](n: I)(using Conversion[I, Int]): TInt[T] | I =
      import scala.language.implicitConversions
      (m: Int) + (n: Int)
1 Like