constant-factor syntax support depends on scala 3.4 (?)
Opened this issue · 1 comments
erikerlandson commented
Syntax support for constant factor multiplication or division, aka 2 * q
or q / 2
, etc, using the new scala 3 extension
feature, currently is not feasible.
SIP-54 will probably fix this, which lands in scala 3.4
scala/scala3#17660
Here is a simplified example of the failure:
object repro:
case class Repro[V](value: V)
object Repro:
extension[V](r: Repro[V])
inline def *(rr: Repro[V])(using
num: scala.math.Numeric[V]
): Repro[V] =
Repro(num.times(r.value, rr.value))
inline def /(rr: Repro[V])(using
num: scala.math.Fractional[V]
): Repro[V] =
Repro(num.div(r.value, rr.value))
object extend:
import repro.Repro
extension(v: Int)
inline def *[V](r: Repro[V])(using
num: scala.math.Numeric[V]
): Repro[V] =
Repro(num.times(num.fromInt(v), r.value))
inline def /[V](r: Repro[V])(using
num: scala.math.Fractional[V]
): Repro[V] =
Repro(num.times(num.fromInt(v), r.value))
extension[V](r: Repro[V])
inline def *(v: Int)(using
num: scala.math.Numeric[V]
): Repro[V] =
Repro(num.times(r.value, num.fromInt(v)))
inline def /(v: Int)(using
num: scala.math.Fractional[V]
): Repro[V] =
Repro(num.div(r.value, num.fromInt(v)))
scala> val r = Repro(2.0)
val r: coulomb.ops.syntax.coef.repro.Repro[Double] = Repro(2.0)
scala> 2 * r
val res0: coulomb.ops.syntax.coef.repro.Repro[Double] = Repro(4.0)
scala> r * r
-- [E007] Type Mismatch Error: -------------------------------------------------
1 |r * r
| ^
| Found: (r : coulomb.ops.syntax.coef.repro.Repro[Double])
| Required: Int
|
| longer explanation available when compiling with `-explain`
1 error found
scala> r / 2
val res1: coulomb.ops.syntax.coef.repro.Repro[Double] = Repro(1.0)
scala> 2 / r
val res2: coulomb.ops.syntax.coef.repro.Repro[Double] = Repro(4.0)
scala> r / r
-- [E007] Type Mismatch Error: -------------------------------------------------
1 |r / r
| ^
| Found: (r : coulomb.ops.syntax.coef.repro.Repro[Double])
| Required: Int
|
| longer explanation available when compiling with `-explain`
1 error found
erikerlandson commented
Here's a prototype of what I'm thinking:
package coulomb.ops.syntax.coef
object all:
export int.*
export double.*
object int:
extension(v: Int)
inline def *[V, U](q: Quantity[V, U])(using
vc: ValueConversion[Int, V],
alg: MultiplicativeSemigroup[V]
): Quantity[V, U] =
alg.times(vc(v), q.value).withUnit[U]
transparent inline def /[V, U](q: Quantity[V, U])(using
vc: ValueConversion[Int, V],
alg: MultiplicativeGroup[V],
su: SimplifiedUnit[1 / U]
): Quantity[V, su.UO] =
alg.div(vc(v), q.value).withUnit[su.UO]
extension[V, U](q: Quantity[V, U])
inline def *(v: Int)(using
vc: ValueConversion[Int, V],
alg: MultiplicativeSemigroup[V]
): Quantity[V, U] =
alg.times(q.value, vc(v)).withUnit[U]
transparent inline def /(v: Int)(using
vc: ValueConversion[Int, V],
alg: MultiplicativeGroup[V]
): Quantity[V, U] =
alg.div(q.value, vc(v)).withUnit[U]
object double:
extension(v: Double)
inline def *[V, U](q: Quantity[V, U])(using
vc: ValueConversion[Double, V],
alg: MultiplicativeSemigroup[V]
): Quantity[V, U] =
alg.times(vc(v), q.value).withUnit[U]
extension[V, U](q: Quantity[V, U])
inline def *(v: Double)(using
vc: ValueConversion[Double, V],
alg: MultiplicativeSemigroup[V]
): Quantity[V, U] =
alg.times(q.value, vc(v)).withUnit[U]