Open
Description
Compiler version
3.1.2-RC1-bin-20211102-82172ed-NIGHTLY
Minimized code
I've found it really hard to minimize this due too all the moving components.
You can click the little triangle to see the full attempt.
Here are the bits where I think it goes wrong:
// a generated group of tests for type V
// reduced from a collection of these
val condUpperBoundPartialOrdering: [V] => () => TestGroup[V]
// a function that check if a group of tests applies to a specific object
// inline here is necessary for it to work (the positive case)
inline def appliesTo[V](tl: TestLattice[_, V], v: TestGroup[V]): Boolean
// applying the test check to an object
// reduced form a "reduce"
def app[X, Y](x: X, f: X => Y): Y
// a generated group of tests for type V
// reduced from a collection of these
val condUpperBoundPartialOrdering: [V] => () => TestGroup[V]
// a function that check if a group of tests applies to a specific object
// inline here is necessary for it to work (the positive case)
inline def appliesTo[V](tl: TestLattice[_, V], v: TestGroup[V]): Boolean
// applying the test check to an object
// reduced form a "reduce"
def app[X, Y](x: X, f: X => Y): Y
// Necesarry abstract definitions
trait JoinLattice[A] extends PartialOrdering[A]:
override def tryCompare(x: A, y: A): Option[0 | 1 | -1] = ???
override def lteq(x: A, y: A): Boolean = ???
trait UpperBound[A]
trait LowerBound[A]
trait Finite[A]:
val elements: Set[A]
trait Atomic[A] extends LowerBound[A]
trait CoAtomic[A] extends UpperBound[A]
trait BoundedJoinLattice[A] extends JoinLattice[A] with LowerBound[A]
trait DoubleBoundedJoinLattice[A] extends BoundedJoinLattice[A] with UpperBound[A]
trait AtomicJoinLattice[A] extends BoundedJoinLattice[A] with Atomic[A]
trait BoundedCoAtomicJoinLattice[A] extends BoundedJoinLattice[A] with CoAtomic[A]
trait DoubleAtomicJoinLattice[A] extends BoundedCoAtomicJoinLattice[A] with AtomicJoinLattice[A]
trait FiniteDoubleAtomicJoinLattice[A] extends DoubleAtomicJoinLattice[A] with Finite[A]
// Necesarry concrete definitions
def optionsLattice[A](options: Seq[A]) = new FiniteDoubleAtomicJoinLattice[Set[A]]:
val elements = options.toSet.subsets.toSet
def evidenceLattice[A] = new BoundedJoinLattice[(Set[A], Set[A])] {}
// Test utils
abstract class TestGroup[V]:
type R
val group: String
case class TestLattice[R, V](val name: String, lattice: R, elements: Iterable[V]):
type Lattice = R
type Carrier = V
object TestLattice:
def fromFinite[R <: Finite[V], V](name: String, lattice: R) =
TestLattice(name, lattice, lattice.elements)
// Util for example
def app[X, Y](x: X, f: X => Y) = f(x)
inline def appliesTo[V](tl: TestLattice[_, V], v: TestGroup[V]) =
tl.lattice match
case q: v.R => println(("matches", v, q))
case q => println(("misses", v, q))
// Values for example
val to_test = Seq(
TestLattice("Evidence (Set, Set)", evidenceLattice[Int], {
val range = (0 to 3).toSet.subsets.toSet
for x <- range; y <- range yield (x, y)
}),
TestLattice.fromFinite("Options (Set)", optionsLattice(1 to 4))
)
val condUpperBoundPartialOrdering = [V] => () => new TestGroup[V]:
type R = UpperBound[V] & PartialOrdering[V]
val group = "UpperBound PartialOrdering laws"
@main def example =
for ins <- to_test do
// this works correctly
app(condUpperBoundPartialOrdering[ins.Carrier](), v => appliesTo(ins, v))
// this does not compile
// app(condUpperBoundPartialOrdering, v => appliesTo(ins, v[ins.Carrier]()))
Output
[error] | app(condUpperBoundPartialOrdering, v => appliesTo(ins, v[ins.Carrier]()))
[error] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[error] |Found: ([V] => () => TestGroup[V]{R = IP.lib.UpperBound[V] & PartialOrdering[V]}) =>
[error] | Unit
[error] |Required: ([V] => () => TestGroup[Any]{R = IP.lib.UpperBound[Any] & PartialOrdering[Any]}) =>
[error] | Unit
Expectation
Work the same as
app(condUpperBoundPartialOrdering[ins.Carrier](), v => appliesTo(ins, v))
Two things here:
- I kinda expect
([V] => () => TestGroup[V]{R = IP.lib.UpperBound[V] & PartialOrdering[V]})
to match type([V] => () => TestGroup[Any]{R = IP.lib.UpperBound[Any] & PartialOrdering[Any]})
? - I expect
(λx.G) (f v)
to be equivalent to(λx.G[x := (f x)]) v
.