Skip to content

Type check for polymorphic function types #13918

Open
@Adam-Vandervorst

Description

@Adam-Vandervorst

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
// 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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions