-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Closed
Description
I was playing a bit with opaque types and encountered what at least to me seems like some strange behavior. If I define an opaque type Nat and then want to refer to that type in a function definition at use site I need to use Nat.Nat. Nat seems to only refer to the companion object versus the opaque type itself. This is inconsistent with the treatment of other types. For example, if I defined Nat as a case class with a companion object then I could use Nat to refer to the type itself in a function definition. This seems less than ideal since I think one of the goals of opaque types was for them to be treated like any other type at use site. Is this intended behavior or a bug? Example below:
object Library {
opaque type Nat = Int
object Nat {
def apply(n: Int): Nat = {
require(n >= 0)
n
}
def times(x: Nat, y: Nat): Nat = x * y
def toInt(n: Nat): Int = n
implicit class NatOps(val self: Nat) extends AnyVal {
def *(other: Nat): Nat = self * other
def toInt: Int = self
}
}
}
object User extends App {
import Library._
val x = Nat(3)
val y = Nat(4)
val a = x * y // inferred type is Library.Nat.Nat
val b = double1(x) // inferred type is Library.Nat
val c = double2(x) // inferred type is Library.Nat.Nat
assert(a.toInt == 12) // works
//assert(b.toInt == 6) // error: toInt is not a member of Library.Nat
assert(c.toInt == 6) // works
//def double0(n: Nat): Nat = n * Nat(2) // error
def double1(n: Nat.Nat): Nat = n * Nat(2) // output type is incorrect
def double2(n: Nat.Nat): Nat.Nat =n * Nat(2) // works
}
Metadata
Metadata
Assignees
Labels
No labels